From f764a5c8c0c973a1996b2f86e009b592771bd8c4 Mon Sep 17 00:00:00 2001 From: yangguo Date: Fri, 24 Mar 2017 03:54:55 -0700 Subject: [PATCH] [debug] extend debug-evaluate by Map builtins. R=jgruber@chromium.org BUG=v8:5821 Review-Url: https://codereview.chromium.org/2772853003 Cr-Commit-Position: refs/heads/master@{#44092} --- src/debug/debug-evaluate.cc | 123 ++++++++++-------- ...ebug-evaluate-no-side-effect-builtins-2.js | 18 +++ 2 files changed, 84 insertions(+), 57 deletions(-) diff --git a/src/debug/debug-evaluate.cc b/src/debug/debug-evaluate.cc index 176c0dfb76..8937c89ab2 100644 --- a/src/debug/debug-evaluate.cc +++ b/src/debug/debug-evaluate.cc @@ -259,64 +259,68 @@ void DebugEvaluate::ContextBuilder::MaterializeReceiver( namespace { bool IntrinsicHasNoSideEffect(Runtime::FunctionId id) { +// Use macro to include both inlined and non-inlined version of an intrinsic. +#define INTRINSIC_WHITELIST(V) \ + /* Conversions */ \ + V(ToInteger) \ + V(ToObject) \ + V(ToString) \ + V(ToLength) \ + V(ToNumber) \ + /* Type checks */ \ + V(IsJSReceiver) \ + V(IsSmi) \ + V(IsArray) \ + V(IsFunction) \ + V(IsDate) \ + V(IsJSProxy) \ + V(IsRegExp) \ + V(IsTypedArray) \ + V(ClassOf) \ + /* Loads */ \ + V(LoadLookupSlotForCall) \ + /* Arrays */ \ + V(ArraySpeciesConstructor) \ + V(NormalizeElements) \ + V(GetArrayKeys) \ + V(HasComplexElements) \ + V(EstimateNumberOfElements) \ + /* Errors */ \ + V(ReThrow) \ + V(ThrowReferenceError) \ + V(ThrowSymbolIteratorInvalid) \ + V(ThrowIteratorResultNotAnObject) \ + V(NewTypeError) \ + /* Strings */ \ + V(StringCharCodeAt) \ + V(StringIndexOf) \ + V(StringReplaceOneCharWithString) \ + V(SubString) \ + V(RegExpInternalReplace) \ + /* Literals */ \ + V(CreateArrayLiteral) \ + V(CreateObjectLiteral) \ + V(CreateRegExpLiteral) \ + /* Collections */ \ + V(JSCollectionGetTable) \ + V(FixedArrayGet) \ + V(StringGetRawHashField) \ + V(GenericHash) \ + V(MapIteratorInitialize) \ + V(MapInitialize) \ + /* Misc. */ \ + V(ForInPrepare) \ + V(Call) \ + V(MaxSmi) \ + V(HasInPrototypeChain) + +#define CASE(Name) \ + case Runtime::k##Name: \ + case Runtime::kInline##Name: + switch (id) { - // Whitelist for intrinsics and 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: - case Runtime::kToNumber: - // Type checks. - case Runtime::kIsJSReceiver: - case Runtime::kInlineIsJSReceiver: - case Runtime::kIsSmi: - case Runtime::kInlineIsSmi: - case Runtime::kIsArray: - case Runtime::kInlineIsArray: - case Runtime::kIsFunction: - case Runtime::kIsDate: - case Runtime::kIsJSProxy: - case Runtime::kIsRegExp: - case Runtime::kIsTypedArray: - // Loads. - case Runtime::kLoadLookupSlotForCall: - // Arrays. - case Runtime::kArraySpeciesConstructor: - case Runtime::kNormalizeElements: - case Runtime::kGetArrayKeys: - case Runtime::kHasComplexElements: - case Runtime::kEstimateNumberOfElements: - // Errors. - case Runtime::kReThrow: - case Runtime::kThrowReferenceError: - case Runtime::kThrowSymbolIteratorInvalid: - case Runtime::kThrowIteratorResultNotAnObject: - case Runtime::kNewTypeError: - // Strings. - case Runtime::kInlineStringCharCodeAt: - case Runtime::kStringCharCodeAt: - case Runtime::kStringIndexOf: - case Runtime::kStringReplaceOneCharWithString: - case Runtime::kSubString: - case Runtime::kInlineSubString: - case Runtime::kRegExpInternalReplace: - // Literals. - case Runtime::kCreateArrayLiteral: - case Runtime::kCreateObjectLiteral: - case Runtime::kCreateRegExpLiteral: - // Misc. - case Runtime::kForInPrepare: - case Runtime::kInlineCall: - case Runtime::kCall: - case Runtime::kInlineMaxSmi: - case Runtime::kMaxSmi: - case Runtime::kHasInPrototypeChain: - return true; + INTRINSIC_WHITELIST(CASE) + return true; default: if (FLAG_trace_side_effect_free_debug_evaluate) { PrintF("[debug-evaluate] intrinsic %s may cause side effect.\n", @@ -324,6 +328,9 @@ bool IntrinsicHasNoSideEffect(Runtime::FunctionId id) { } return false; } + +#undef CASE +#undef INTRINSIC_WHITELIST } bool BytecodeHasNoSideEffect(interpreter::Bytecode bytecode) { @@ -556,6 +563,8 @@ bool BuiltinHasNoSideEffect(Builtins::Name id) { case Builtins::kGlobalEncodeURIComponent: case Builtins::kGlobalEscape: case Builtins::kGlobalUnescape: + case Builtins::kGlobalIsFinite: + case Builtins::kGlobalIsNaN: // Error builtins. case Builtins::kMakeError: case Builtins::kMakeTypeError: diff --git a/test/debugger/debug/debug-evaluate-no-side-effect-builtins-2.js b/test/debugger/debug/debug-evaluate-no-side-effect-builtins-2.js index 188ee09293..2e82cf2729 100644 --- a/test/debugger/debug/debug-evaluate-no-side-effect-builtins-2.js +++ b/test/debugger/debug/debug-evaluate-no-side-effect-builtins-2.js @@ -8,6 +8,7 @@ Debug = debug.Debug var exception = null; var date = new Date(); +var map = new Map().set("a", "b").set("c", "d"); function listener(event, exec_state, event_data, data) { if (event != Debug.DebugEvent.Break) return; @@ -51,6 +52,23 @@ function listener(event, exec_state, event_data, data) { success("abc", `encodeURIComponent("abc")`); success("abc", `escape("abc")`); success("abc", `unescape("abc")`); + success(true, `isFinite(0)`); + success(true, `isNaN(0/0)`); + + // Test Map functions. + success(undefined, `new Map()`); + success("[object Map]", `map.toString()`); + success("b", `map.get("a")`); + success(true, `map.get("x") === undefined`); + success(undefined, `map.entries()`); + success(undefined, `map.keys()`); + success(undefined, `map.values()`); + success(2, `map.size`); + fail(`map.has("c")`); // This sets a hash on the object. + fail(`map.forEach(()=>1)`); + fail(`map.delete("a")`); + fail(`map.clear()`); + fail(`map.set("x", "y")`); } catch (e) { exception = e; print(e, e.stack);