Index: src/debug/debug-evaluate.cc |
diff --git a/src/debug/debug-evaluate.cc b/src/debug/debug-evaluate.cc |
index d291441d924e11812c1b383a3ff0cd78aa99f5f4..96cd98d3f26a2b47e997cb69dada1c1a92fb8744 100644 |
--- a/src/debug/debug-evaluate.cc |
+++ b/src/debug/debug-evaluate.cc |
@@ -258,31 +258,44 @@ void DebugEvaluate::ContextBuilder::MaterializeReceiver( |
namespace { |
bool IntrinsicHasNoSideEffect(Runtime::FunctionId id) { |
- DCHECK_EQ(Runtime::INLINE, Runtime::FunctionForId(id)->intrinsic_type); |
switch (id) { |
- // Whitelist for intrinsics. |
- case Runtime::kInlineToObject: |
- return true; |
- default: |
- if (FLAG_trace_side_effect_free_debug_evaluate) { |
- PrintF("[debug-evaluate] intrinsic %s may cause side effect.\n", |
- Runtime::FunctionForId(id)->name); |
- } |
- return false; |
- } |
-} |
- |
-bool RuntimeFunctionHasNoSideEffect(Runtime::FunctionId id) { |
- DCHECK_EQ(Runtime::RUNTIME, Runtime::FunctionForId(id)->intrinsic_type); |
- switch (id) { |
- // Whitelist for runtime functions. |
+ // Whitelist for intrinsics amd runtime functions. |
+ // Conversions. |
+ case Runtime::kToInteger: |
+ case Runtime::kInlineToInteger: |
case Runtime::kToObject: |
+ case Runtime::kInlineToObject: |
+ case Runtime::kToString: |
+ case Runtime::kInlineToString: |
+ case Runtime::kToLength: |
+ case Runtime::kInlineToLength: |
+ // Loads. |
case Runtime::kLoadLookupSlotForCall: |
+ // Errors. |
case Runtime::kThrowReferenceError: |
+ // Strings. |
+ case Runtime::kInlineStringCharCodeAt: |
+ case Runtime::kStringCharCodeAt: |
+ case Runtime::kStringIndexOf: |
+ case Runtime::kStringReplaceOneCharWithString: |
+ case Runtime::kSubString: |
+ case Runtime::kInlineSubString: |
+ case Runtime::kStringToLowerCase: |
+ case Runtime::kStringToUpperCase: |
+ case Runtime::kRegExpInternalReplace: |
+ // Literals. |
+ case Runtime::kCreateArrayLiteral: |
+ case Runtime::kCreateObjectLiteral: |
+ case Runtime::kCreateRegExpLiteral: |
+ // Misc. |
+ case Runtime::kInlineCall: |
+ case Runtime::kCall: |
+ case Runtime::kInlineMaxSmi: |
+ case Runtime::kMaxSmi: |
return true; |
default: |
if (FLAG_trace_side_effect_free_debug_evaluate) { |
- PrintF("[debug-evaluate] runtime %s may cause side effect.\n", |
+ PrintF("[debug-evaluate] intrinsic %s may cause side effect.\n", |
Runtime::FunctionForId(id)->name); |
} |
return false; |
@@ -294,16 +307,56 @@ bool BytecodeHasNoSideEffect(interpreter::Bytecode bytecode) { |
typedef interpreter::Bytecodes Bytecodes; |
if (Bytecodes::IsWithoutExternalSideEffects(bytecode)) return true; |
if (Bytecodes::IsCallOrNew(bytecode)) return true; |
+ if (Bytecodes::WritesBooleanToAccumulator(bytecode)) return true; |
+ if (Bytecodes::IsJumpIfToBoolean(bytecode)) return true; |
+ if (Bytecodes::IsPrefixScalingBytecode(bytecode)) return true; |
switch (bytecode) { |
// Whitelist for bytecodes. |
- case Bytecode::kStackCheck: |
+ // Loads. |
case Bytecode::kLdaLookupSlot: |
case Bytecode::kLdaGlobal: |
case Bytecode::kLdaNamedProperty: |
case Bytecode::kLdaKeyedProperty: |
+ // Arithmetics. |
case Bytecode::kAdd: |
- case Bytecode::kReturn: |
+ case Bytecode::kAddSmi: |
+ case Bytecode::kSub: |
+ case Bytecode::kSubSmi: |
+ case Bytecode::kMul: |
+ case Bytecode::kDiv: |
+ case Bytecode::kMod: |
+ case Bytecode::kBitwiseAnd: |
+ case Bytecode::kBitwiseAndSmi: |
+ case Bytecode::kBitwiseOr: |
+ case Bytecode::kBitwiseOrSmi: |
+ case Bytecode::kBitwiseXor: |
+ case Bytecode::kShiftLeft: |
+ case Bytecode::kShiftLeftSmi: |
+ case Bytecode::kShiftRight: |
+ case Bytecode::kShiftRightSmi: |
+ case Bytecode::kShiftRightLogical: |
+ case Bytecode::kInc: |
+ case Bytecode::kDec: |
+ case Bytecode::kLogicalNot: |
+ case Bytecode::kToBooleanLogicalNot: |
+ case Bytecode::kTypeOf: |
+ // Contexts. |
+ case Bytecode::kCreateBlockContext: |
case Bytecode::kCreateCatchContext: |
+ case Bytecode::kCreateFunctionContext: |
+ case Bytecode::kCreateEvalContext: |
+ case Bytecode::kCreateWithContext: |
+ // Literals. |
+ case Bytecode::kCreateArrayLiteral: |
+ case Bytecode::kCreateObjectLiteral: |
+ case Bytecode::kCreateRegExpLiteral: |
+ // Misc. |
+ case Bytecode::kCreateUnmappedArguments: |
+ case Bytecode::kThrow: |
+ case Bytecode::kIllegal: |
+ case Bytecode::kCallJSRuntime: |
+ case Bytecode::kStackCheck: |
+ case Bytecode::kReturn: |
case Bytecode::kSetPendingMessage: |
return true; |
default: |
@@ -318,7 +371,76 @@ bool BytecodeHasNoSideEffect(interpreter::Bytecode bytecode) { |
bool BuiltinHasNoSideEffect(Builtins::Name id) { |
switch (id) { |
// Whitelist for builtins. |
+ // Math builtins. |
+ case Builtins::kMathAbs: |
+ case Builtins::kMathAcos: |
+ case Builtins::kMathAcosh: |
+ case Builtins::kMathAsin: |
+ case Builtins::kMathAsinh: |
+ case Builtins::kMathAtan: |
+ case Builtins::kMathAtanh: |
+ case Builtins::kMathAtan2: |
+ case Builtins::kMathCeil: |
+ case Builtins::kMathCbrt: |
+ case Builtins::kMathExpm1: |
+ case Builtins::kMathClz32: |
+ case Builtins::kMathCos: |
+ case Builtins::kMathCosh: |
+ case Builtins::kMathExp: |
+ case Builtins::kMathFloor: |
+ case Builtins::kMathFround: |
+ case Builtins::kMathHypot: |
+ case Builtins::kMathImul: |
+ case Builtins::kMathLog: |
+ case Builtins::kMathLog1p: |
+ case Builtins::kMathLog2: |
+ case Builtins::kMathLog10: |
+ case Builtins::kMathMax: |
+ case Builtins::kMathMin: |
+ case Builtins::kMathPow: |
+ case Builtins::kMathRandom: |
+ case Builtins::kMathRound: |
+ case Builtins::kMathSign: |
case Builtins::kMathSin: |
+ case Builtins::kMathSinh: |
+ case Builtins::kMathSqrt: |
+ case Builtins::kMathTan: |
+ case Builtins::kMathTanh: |
+ case Builtins::kMathTrunc: |
+ // Number builtins. |
+ case Builtins::kNumberConstructor: |
+ case Builtins::kNumberIsFinite: |
+ case Builtins::kNumberIsInteger: |
+ case Builtins::kNumberIsNaN: |
+ case Builtins::kNumberIsSafeInteger: |
+ case Builtins::kNumberParseFloat: |
+ case Builtins::kNumberParseInt: |
+ case Builtins::kNumberPrototypeToExponential: |
+ case Builtins::kNumberPrototypeToFixed: |
+ case Builtins::kNumberPrototypeToPrecision: |
+ case Builtins::kNumberPrototypeToString: |
+ case Builtins::kNumberPrototypeValueOf: |
+ // String builtins. Strings are immutable. |
+ case Builtins::kStringFromCharCode: |
+ case Builtins::kStringFromCodePoint: |
+ case Builtins::kStringConstructor: |
+ case Builtins::kStringPrototypeCharAt: |
+ case Builtins::kStringPrototypeCharCodeAt: |
+ case Builtins::kStringPrototypeEndsWith: |
+ case Builtins::kStringPrototypeIncludes: |
+ case Builtins::kStringPrototypeIndexOf: |
+ case Builtins::kStringPrototypeLastIndexOf: |
+ case Builtins::kStringPrototypeStartsWith: |
+ case Builtins::kStringPrototypeSubstr: |
+ case Builtins::kStringPrototypeSubstring: |
+ case Builtins::kStringPrototypeToString: |
+ case Builtins::kStringPrototypeTrim: |
+ case Builtins::kStringPrototypeTrimLeft: |
+ case Builtins::kStringPrototypeTrimRight: |
+ case Builtins::kStringPrototypeValueOf: |
+ // JSON builtins. |
+ case Builtins::kJsonParse: |
+ case Builtins::kJsonStringify: |
return true; |
default: |
if (FLAG_trace_side_effect_free_debug_evaluate) { |
@@ -354,13 +476,11 @@ bool DebugEvaluate::FunctionHasNoSideEffect(Handle<SharedFunctionInfo> info) { |
interpreter::Bytecode bytecode = it.current_bytecode(); |
if (interpreter::Bytecodes::IsCallRuntime(bytecode)) { |
- if (bytecode == interpreter::Bytecode::kInvokeIntrinsic) { |
- Runtime::FunctionId id = it.GetIntrinsicIdOperand(0); |
- if (IntrinsicHasNoSideEffect(id)) continue; |
- } else { |
- Runtime::FunctionId id = it.GetRuntimeIdOperand(0); |
- if (RuntimeFunctionHasNoSideEffect(id)) continue; |
- } |
+ Runtime::FunctionId id = |
+ (bytecode == interpreter::Bytecode::kInvokeIntrinsic) |
+ ? it.GetIntrinsicIdOperand(0) |
+ : it.GetRuntimeIdOperand(0); |
+ if (IntrinsicHasNoSideEffect(id)) continue; |
return false; |
} |