LCOV - code coverage report
Current view: top level - src/debug - debug-evaluate.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 119 124 96.0 %
Date: 2017-10-20 Functions: 11 11 100.0 %

          Line data    Source code
       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
       3             : // found in the LICENSE file.
       4             : 
       5             : #include "src/debug/debug-evaluate.h"
       6             : 
       7             : #include "src/accessors.h"
       8             : #include "src/assembler-inl.h"
       9             : #include "src/compiler.h"
      10             : #include "src/contexts.h"
      11             : #include "src/debug/debug-frames.h"
      12             : #include "src/debug/debug-scopes.h"
      13             : #include "src/debug/debug.h"
      14             : #include "src/frames-inl.h"
      15             : #include "src/globals.h"
      16             : #include "src/interpreter/bytecode-array-iterator.h"
      17             : #include "src/interpreter/bytecodes.h"
      18             : #include "src/isolate-inl.h"
      19             : 
      20             : namespace v8 {
      21             : namespace internal {
      22             : 
      23          10 : static inline bool IsDebugContext(Isolate* isolate, Context* context) {
      24             :   return context->native_context() == *isolate->debug()->debug_context();
      25             : }
      26             : 
      27           5 : MaybeHandle<Object> DebugEvaluate::Global(Isolate* isolate,
      28             :                                           Handle<String> source) {
      29             :   // Handle the processing of break.
      30             :   DisableBreak disable_break_scope(isolate->debug());
      31             : 
      32             :   // Enter the top context from before the debugger was invoked.
      33          10 :   SaveContext save(isolate);
      34           5 :   SaveContext* top = &save;
      35          25 :   while (top != nullptr && IsDebugContext(isolate, *top->context())) {
      36             :     top = top->prev();
      37             :   }
      38           5 :   if (top != nullptr) isolate->set_context(*top->context());
      39             : 
      40             :   // Get the native context now set to the top context from before the
      41             :   // debugger was invoked.
      42           5 :   Handle<Context> context = isolate->native_context();
      43           5 :   Handle<JSObject> receiver(context->global_proxy());
      44             :   Handle<SharedFunctionInfo> outer_info(context->closure()->shared(), isolate);
      45          10 :   return Evaluate(isolate, outer_info, context, receiver, source, false);
      46             : }
      47             : 
      48       10491 : MaybeHandle<Object> DebugEvaluate::Local(Isolate* isolate,
      49             :                                          StackFrame::Id frame_id,
      50             :                                          int inlined_jsframe_index,
      51             :                                          Handle<String> source,
      52             :                                          bool throw_on_side_effect) {
      53             :   // Handle the processing of break.
      54             :   DisableBreak disable_break_scope(isolate->debug());
      55             : 
      56             :   // Get the frame where the debugging is performed.
      57       10491 :   StackTraceFrameIterator it(isolate, frame_id);
      58       10491 :   if (!it.is_javascript()) return isolate->factory()->undefined_value();
      59             :   JavaScriptFrame* frame = it.javascript_frame();
      60             : 
      61             :   // Traverse the saved contexts chain to find the active context for the
      62             :   // selected frame.
      63             :   SaveContext* save =
      64       10491 :       DebugFrameHelper::FindSavedContextForFrame(isolate, frame);
      65       20982 :   SaveContext savex(isolate);
      66             :   isolate->set_context(*(save->context()));
      67             : 
      68             :   // This is not a lot different than DebugEvaluate::Global, except that
      69             :   // variables accessible by the function we are evaluating from are
      70             :   // materialized and included on top of the native context. Changes to
      71             :   // the materialized object are written back afterwards.
      72             :   // Note that the native context is taken from the original context chain,
      73             :   // which may not be the current native context of the isolate.
      74       10491 :   ContextBuilder context_builder(isolate, frame, inlined_jsframe_index);
      75       10491 :   if (isolate->has_pending_exception()) return MaybeHandle<Object>();
      76             : 
      77             :   Handle<Context> context = context_builder.evaluation_context();
      78       10491 :   Handle<JSObject> receiver(context->global_proxy());
      79             :   MaybeHandle<Object> maybe_result =
      80             :       Evaluate(isolate, context_builder.outer_info(), context, receiver, source,
      81       20982 :                throw_on_side_effect);
      82       10491 :   if (!maybe_result.is_null()) context_builder.UpdateValues();
      83       10491 :   return maybe_result;
      84             : }
      85             : 
      86             : 
      87             : // Compile and evaluate source for the given context.
      88       10496 : MaybeHandle<Object> DebugEvaluate::Evaluate(
      89             :     Isolate* isolate, Handle<SharedFunctionInfo> outer_info,
      90             :     Handle<Context> context, Handle<Object> receiver, Handle<String> source,
      91             :     bool throw_on_side_effect) {
      92             :   Handle<JSFunction> eval_fun;
      93       20992 :   ASSIGN_RETURN_ON_EXCEPTION(
      94             :       isolate, eval_fun,
      95             :       Compiler::GetFunctionFromEval(source, outer_info, context,
      96             :                                     LanguageMode::kSloppy, NO_PARSE_RESTRICTION,
      97             :                                     kNoSourcePosition, kNoSourcePosition,
      98             :                                     kNoSourcePosition),
      99             :       Object);
     100             : 
     101             :   Handle<Object> result;
     102             :   {
     103       10432 :     NoSideEffectScope no_side_effect(isolate, throw_on_side_effect);
     104       20864 :     ASSIGN_RETURN_ON_EXCEPTION(
     105             :         isolate, result,
     106        9566 :         Execution::Call(isolate, eval_fun, receiver, 0, nullptr), Object);
     107             :   }
     108             : 
     109             :   // Skip the global proxy as it has no properties and always delegates to the
     110             :   // real global object.
     111        9566 :   if (result->IsJSGlobalProxy()) {
     112          18 :     PrototypeIterator iter(isolate, Handle<JSGlobalProxy>::cast(result));
     113             :     // TODO(verwaest): This will crash when the global proxy is detached.
     114             :     result = PrototypeIterator::GetCurrent<JSObject>(iter);
     115             :   }
     116             : 
     117        9566 :   return result;
     118             : }
     119             : 
     120             : 
     121       10491 : DebugEvaluate::ContextBuilder::ContextBuilder(Isolate* isolate,
     122             :                                               JavaScriptFrame* frame,
     123             :                                               int inlined_jsframe_index)
     124             :     : isolate_(isolate),
     125             :       frame_(frame),
     126       10491 :       inlined_jsframe_index_(inlined_jsframe_index) {
     127       10491 :   FrameInspector frame_inspector(frame, inlined_jsframe_index, isolate);
     128             :   Handle<JSFunction> local_function = frame_inspector.GetFunction();
     129             :   Handle<Context> outer_context(local_function->context());
     130       10491 :   evaluation_context_ = outer_context;
     131       10491 :   outer_info_ = handle(local_function->shared());
     132             :   Factory* factory = isolate->factory();
     133             : 
     134             :   // To evaluate as if we were running eval at the point of the debug break,
     135             :   // we reconstruct the context chain as follows:
     136             :   //  - To make stack-allocated variables visible, we materialize them and
     137             :   //    use a debug-evaluate context to wrap both the materialized object and
     138             :   //    the original context.
     139             :   //  - We use the original context chain from the function context to the
     140             :   //    native context.
     141             :   //  - Between the function scope and the native context, we only resolve
     142             :   //    variable names that the current function already uses. Only for these
     143             :   //    names we can be sure that they will be correctly resolved. For the
     144             :   //    rest, we only resolve to with, script, and native contexts. We use a
     145             :   //    whitelist to implement that.
     146             :   // Context::Lookup has special handling for debug-evaluate contexts:
     147             :   //  - Look up in the materialized stack variables.
     148             :   //  - Look up in the original context.
     149             :   //  - Check the whitelist to find out whether to skip contexts during lookup.
     150             :   const ScopeIterator::Option option = ScopeIterator::COLLECT_NON_LOCALS;
     151       21726 :   for (ScopeIterator it(isolate, &frame_inspector, option); !it.Done();
     152         744 :        it.Next()) {
     153       11225 :     ScopeIterator::ScopeType scope_type = it.Type();
     154       11225 :     if (scope_type == ScopeIterator::ScopeTypeLocal) {
     155             :       DCHECK_EQ(FUNCTION_SCOPE, it.CurrentScopeInfo()->scope_type());
     156       10148 :       Handle<JSObject> materialized = factory->NewJSObjectWithNullProto();
     157             :       Handle<Context> local_context =
     158       10148 :           it.HasContext() ? it.CurrentContext() : outer_context;
     159       10148 :       Handle<StringSet> non_locals = it.GetNonLocals();
     160             :       MaterializeReceiver(materialized, local_context, local_function,
     161       10148 :                           non_locals);
     162             :       frame_inspector.MaterializeStackLocals(materialized, local_function,
     163       10148 :                                              true);
     164             :       ContextChainElement context_chain_element;
     165       10148 :       context_chain_element.scope_info = it.CurrentScopeInfo();
     166       10148 :       context_chain_element.materialized_object = materialized;
     167             :       // Non-locals that are already being referenced by the current function
     168             :       // are guaranteed to be correctly resolved.
     169       10148 :       context_chain_element.whitelist = non_locals;
     170       10148 :       if (it.HasContext()) {
     171         517 :         context_chain_element.wrapped_context = it.CurrentContext();
     172             :       }
     173       10148 :       context_chain_.push_back(context_chain_element);
     174       10148 :       evaluation_context_ = outer_context;
     175             :       break;
     176        2154 :     } else if (scope_type == ScopeIterator::ScopeTypeCatch ||
     177        1889 :                scope_type == ScopeIterator::ScopeTypeWith ||
     178             :                scope_type == ScopeIterator::ScopeTypeModule) {
     179             :       ContextChainElement context_chain_element;
     180         450 :       Handle<Context> current_context = it.CurrentContext();
     181         450 :       if (!current_context->IsDebugEvaluateContext()) {
     182         450 :         context_chain_element.wrapped_context = current_context;
     183             :       }
     184         450 :       context_chain_.push_back(context_chain_element);
     185        1254 :     } else if (scope_type == ScopeIterator::ScopeTypeBlock ||
     186         627 :                scope_type == ScopeIterator::ScopeTypeEval) {
     187         294 :       Handle<JSObject> materialized = factory->NewJSObjectWithNullProto();
     188             :       frame_inspector.MaterializeStackLocals(materialized,
     189         294 :                                              it.CurrentScopeInfo());
     190             :       ContextChainElement context_chain_element;
     191         294 :       context_chain_element.scope_info = it.CurrentScopeInfo();
     192         294 :       context_chain_element.materialized_object = materialized;
     193         294 :       if (it.HasContext()) {
     194          50 :         context_chain_element.wrapped_context = it.CurrentContext();
     195             :       }
     196         294 :       context_chain_.push_back(context_chain_element);
     197             :     } else {
     198             :       break;
     199             :     }
     200             :   }
     201             : 
     202       21383 :   for (auto rit = context_chain_.rbegin(); rit != context_chain_.rend();
     203             :        rit++) {
     204       10892 :     ContextChainElement element = *rit;
     205             :     Handle<ScopeInfo> scope_info(ScopeInfo::CreateForWithScope(
     206       10892 :         isolate, evaluation_context_->IsNativeContext()
     207             :                      ? Handle<ScopeInfo>::null()
     208       23756 :                      : Handle<ScopeInfo>(evaluation_context_->scope_info())));
     209       10892 :     scope_info->SetIsDebugEvaluateScope();
     210             :     evaluation_context_ = factory->NewDebugEvaluateContext(
     211             :         evaluation_context_, scope_info, element.materialized_object,
     212       10892 :         element.wrapped_context, element.whitelist);
     213       10491 :   }
     214       10491 : }
     215             : 
     216             : 
     217        9561 : void DebugEvaluate::ContextBuilder::UpdateValues() {
     218       29094 :   for (ContextChainElement& element : context_chain_) {
     219        9972 :     if (!element.materialized_object.is_null()) {
     220             :       // Write back potential changes to materialized stack locals to the stack.
     221             :       FrameInspector(frame_, inlined_jsframe_index_, isolate_)
     222             :           .UpdateStackLocalsFromMaterializedObject(element.materialized_object,
     223        9542 :                                                    element.scope_info);
     224             :     }
     225             :   }
     226        9561 : }
     227             : 
     228             : 
     229       10148 : void DebugEvaluate::ContextBuilder::MaterializeReceiver(
     230             :     Handle<JSObject> target, Handle<Context> local_context,
     231             :     Handle<JSFunction> local_function, Handle<StringSet> non_locals) {
     232       10148 :   Handle<Object> recv = isolate_->factory()->undefined_value();
     233             :   Handle<String> name = isolate_->factory()->this_string();
     234       10148 :   if (non_locals->Has(name)) {
     235             :     // 'this' is allocated in an outer context and is is already being
     236             :     // referenced by the current function, so it can be correctly resolved.
     237         234 :     return;
     238       19433 :   } else if (local_function->shared()->scope_info()->HasReceiver() &&
     239        9519 :              !frame_->receiver()->IsTheHole(isolate_)) {
     240       19020 :     recv = handle(frame_->receiver(), isolate_);
     241             :   }
     242       19828 :   JSObject::SetOwnPropertyIgnoreAttributes(target, name, recv, NONE).Check();
     243             : }
     244             : 
     245             : namespace {
     246             : 
     247        2259 : bool IntrinsicHasNoSideEffect(Runtime::FunctionId id) {
     248             : // Use macro to include both inlined and non-inlined version of an intrinsic.
     249             : #define INTRINSIC_WHITELIST(V)       \
     250             :   /* Conversions */                  \
     251             :   V(ToInteger)                       \
     252             :   V(ToObject)                        \
     253             :   V(ToString)                        \
     254             :   V(ToLength)                        \
     255             :   V(ToNumber)                        \
     256             :   V(NumberToString)                  \
     257             :   /* Type checks */                  \
     258             :   V(IsJSReceiver)                    \
     259             :   V(IsSmi)                           \
     260             :   V(IsArray)                         \
     261             :   V(IsFunction)                      \
     262             :   V(IsDate)                          \
     263             :   V(IsJSProxy)                       \
     264             :   V(IsJSMap)                         \
     265             :   V(IsJSSet)                         \
     266             :   V(IsJSWeakMap)                     \
     267             :   V(IsJSWeakSet)                     \
     268             :   V(IsRegExp)                        \
     269             :   V(IsTypedArray)                    \
     270             :   V(ClassOf)                         \
     271             :   /* Loads */                        \
     272             :   V(LoadLookupSlotForCall)           \
     273             :   /* Arrays */                       \
     274             :   V(ArraySpeciesConstructor)         \
     275             :   V(NormalizeElements)               \
     276             :   V(GetArrayKeys)                    \
     277             :   V(HasComplexElements)              \
     278             :   V(EstimateNumberOfElements)        \
     279             :   /* Errors */                       \
     280             :   V(ReThrow)                         \
     281             :   V(ThrowReferenceError)             \
     282             :   V(ThrowSymbolIteratorInvalid)      \
     283             :   V(ThrowIteratorResultNotAnObject)  \
     284             :   V(NewTypeError)                    \
     285             :   V(ThrowInvalidStringLength)        \
     286             :   /* Strings */                      \
     287             :   V(StringIndexOf)                   \
     288             :   V(StringIncludes)                  \
     289             :   V(StringReplaceOneCharWithString)  \
     290             :   V(StringToNumber)                  \
     291             :   V(StringTrim)                      \
     292             :   V(SubString)                       \
     293             :   V(RegExpInternalReplace)           \
     294             :   /* BigInts */                      \
     295             :   V(BigIntEqual)                     \
     296             :   V(BigIntToBoolean)                 \
     297             :   /* Literals */                     \
     298             :   V(CreateArrayLiteral)              \
     299             :   V(CreateObjectLiteral)             \
     300             :   V(CreateRegExpLiteral)             \
     301             :   /* Collections */                  \
     302             :   V(GenericHash)                     \
     303             :   /* Called from builtins */         \
     304             :   V(StringAdd)                       \
     305             :   V(StringParseFloat)                \
     306             :   V(StringParseInt)                  \
     307             :   V(StringCharCodeAt)                \
     308             :   V(StringIndexOfUnchecked)          \
     309             :   V(StringEqual)                     \
     310             :   V(RegExpInitializeAndCompile)      \
     311             :   V(SymbolDescriptiveString)         \
     312             :   V(GenerateRandomNumbers)           \
     313             :   V(GlobalPrint)                     \
     314             :   V(AllocateInNewSpace)              \
     315             :   V(AllocateSeqOneByteString)        \
     316             :   V(AllocateSeqTwoByteString)        \
     317             :   V(ObjectCreate)                    \
     318             :   V(ObjectHasOwnProperty)            \
     319             :   V(ArrayIndexOf)                    \
     320             :   V(ArrayIncludes_Slow)              \
     321             :   V(ArrayIsArray)                    \
     322             :   V(ThrowTypeError)                  \
     323             :   V(ThrowCalledOnNullOrUndefined)    \
     324             :   V(ThrowIncompatibleMethodReceiver) \
     325             :   V(ThrowInvalidHint)                \
     326             :   V(ThrowNotDateError)               \
     327             :   V(ThrowRangeError)                 \
     328             :   V(ToName)                          \
     329             :   V(GetOwnPropertyDescriptor)        \
     330             :   /* Misc. */                        \
     331             :   V(Call)                            \
     332             :   V(MaxSmi)                          \
     333             :   V(NewObject)                       \
     334             :   V(FinalizeInstanceSize)            \
     335             :   V(HasInPrototypeChain)             \
     336             :   V(StringMaxLength)
     337             : 
     338             : #define CASE(Name)       \
     339             :   case Runtime::k##Name: \
     340             :   case Runtime::kInline##Name:
     341             : 
     342        2259 :   switch (id) {
     343             :     INTRINSIC_WHITELIST(CASE)
     344             :     return true;
     345             :     default:
     346         465 :       if (FLAG_trace_side_effect_free_debug_evaluate) {
     347             :         PrintF("[debug-evaluate] intrinsic %s may cause side effect.\n",
     348           0 :                Runtime::FunctionForId(id)->name);
     349             :       }
     350             :       return false;
     351             :   }
     352             : 
     353             : #undef CASE
     354             : #undef INTRINSIC_WHITELIST
     355             : }
     356             : 
     357       62700 : bool BytecodeHasNoSideEffect(interpreter::Bytecode bytecode) {
     358             :   typedef interpreter::Bytecode Bytecode;
     359             :   typedef interpreter::Bytecodes Bytecodes;
     360       62700 :   if (Bytecodes::IsWithoutExternalSideEffects(bytecode)) return true;
     361       25015 :   if (Bytecodes::IsCallOrConstruct(bytecode)) return true;
     362       20244 :   if (Bytecodes::IsJumpIfToBoolean(bytecode)) return true;
     363       19728 :   if (Bytecodes::IsPrefixScalingBytecode(bytecode)) return true;
     364       19728 :   switch (bytecode) {
     365             :     // Whitelist for bytecodes.
     366             :     // Loads.
     367             :     case Bytecode::kLdaLookupSlot:
     368             :     case Bytecode::kLdaGlobal:
     369             :     case Bytecode::kLdaNamedProperty:
     370             :     case Bytecode::kLdaKeyedProperty:
     371             :     // Arithmetics.
     372             :     case Bytecode::kAdd:
     373             :     case Bytecode::kAddSmi:
     374             :     case Bytecode::kSub:
     375             :     case Bytecode::kSubSmi:
     376             :     case Bytecode::kMul:
     377             :     case Bytecode::kMulSmi:
     378             :     case Bytecode::kDiv:
     379             :     case Bytecode::kDivSmi:
     380             :     case Bytecode::kMod:
     381             :     case Bytecode::kModSmi:
     382             :     case Bytecode::kNegate:
     383             :     case Bytecode::kBitwiseAnd:
     384             :     case Bytecode::kBitwiseAndSmi:
     385             :     case Bytecode::kBitwiseNot:
     386             :     case Bytecode::kBitwiseOr:
     387             :     case Bytecode::kBitwiseOrSmi:
     388             :     case Bytecode::kBitwiseXor:
     389             :     case Bytecode::kBitwiseXorSmi:
     390             :     case Bytecode::kShiftLeft:
     391             :     case Bytecode::kShiftLeftSmi:
     392             :     case Bytecode::kShiftRight:
     393             :     case Bytecode::kShiftRightSmi:
     394             :     case Bytecode::kShiftRightLogical:
     395             :     case Bytecode::kShiftRightLogicalSmi:
     396             :     case Bytecode::kInc:
     397             :     case Bytecode::kDec:
     398             :     case Bytecode::kLogicalNot:
     399             :     case Bytecode::kToBooleanLogicalNot:
     400             :     case Bytecode::kTypeOf:
     401             :     // Contexts.
     402             :     case Bytecode::kCreateBlockContext:
     403             :     case Bytecode::kCreateCatchContext:
     404             :     case Bytecode::kCreateFunctionContext:
     405             :     case Bytecode::kCreateEvalContext:
     406             :     case Bytecode::kCreateWithContext:
     407             :     // Literals.
     408             :     case Bytecode::kCreateArrayLiteral:
     409             :     case Bytecode::kCreateEmptyArrayLiteral:
     410             :     case Bytecode::kCreateObjectLiteral:
     411             :     case Bytecode::kCreateEmptyObjectLiteral:
     412             :     case Bytecode::kCreateRegExpLiteral:
     413             :     // Allocations.
     414             :     case Bytecode::kCreateClosure:
     415             :     case Bytecode::kCreateUnmappedArguments:
     416             :     case Bytecode::kCreateRestParameter:
     417             :     // Comparisons.
     418             :     case Bytecode::kTestEqual:
     419             :     case Bytecode::kTestEqualStrict:
     420             :     case Bytecode::kTestLessThan:
     421             :     case Bytecode::kTestLessThanOrEqual:
     422             :     case Bytecode::kTestGreaterThan:
     423             :     case Bytecode::kTestGreaterThanOrEqual:
     424             :     case Bytecode::kTestInstanceOf:
     425             :     case Bytecode::kTestIn:
     426             :     case Bytecode::kTestEqualStrictNoFeedback:
     427             :     case Bytecode::kTestUndetectable:
     428             :     case Bytecode::kTestTypeOf:
     429             :     case Bytecode::kTestUndefined:
     430             :     case Bytecode::kTestNull:
     431             :     // Conversions.
     432             :     case Bytecode::kToObject:
     433             :     case Bytecode::kToNumber:
     434             :     case Bytecode::kToName:
     435             :     // Misc.
     436             :     case Bytecode::kForInEnumerate:
     437             :     case Bytecode::kForInPrepare:
     438             :     case Bytecode::kForInContinue:
     439             :     case Bytecode::kForInNext:
     440             :     case Bytecode::kForInStep:
     441             :     case Bytecode::kThrow:
     442             :     case Bytecode::kReThrow:
     443             :     case Bytecode::kThrowReferenceErrorIfHole:
     444             :     case Bytecode::kThrowSuperNotCalledIfHole:
     445             :     case Bytecode::kThrowSuperAlreadyCalledIfNotHole:
     446             :     case Bytecode::kIllegal:
     447             :     case Bytecode::kCallJSRuntime:
     448             :     case Bytecode::kStackCheck:
     449             :     case Bytecode::kReturn:
     450             :     case Bytecode::kSetPendingMessage:
     451             :       return true;
     452             :     default:
     453         387 :       if (FLAG_trace_side_effect_free_debug_evaluate) {
     454             :         PrintF("[debug-evaluate] bytecode %s may cause side effect.\n",
     455           0 :                Bytecodes::ToString(bytecode));
     456             :       }
     457             :       return false;
     458             :   }
     459             : }
     460             : 
     461        3744 : bool BuiltinHasNoSideEffect(Builtins::Name id) {
     462        3744 :   switch (id) {
     463             :     // Whitelist for builtins.
     464             :     // Object builtins.
     465             :     case Builtins::kObjectConstructor:
     466             :     case Builtins::kObjectCreate:
     467             :     case Builtins::kObjectEntries:
     468             :     case Builtins::kObjectGetOwnPropertyDescriptor:
     469             :     case Builtins::kObjectGetOwnPropertyDescriptors:
     470             :     case Builtins::kObjectGetOwnPropertyNames:
     471             :     case Builtins::kObjectGetOwnPropertySymbols:
     472             :     case Builtins::kObjectGetPrototypeOf:
     473             :     case Builtins::kObjectIs:
     474             :     case Builtins::kObjectIsExtensible:
     475             :     case Builtins::kObjectIsFrozen:
     476             :     case Builtins::kObjectIsSealed:
     477             :     case Builtins::kObjectPrototypeValueOf:
     478             :     case Builtins::kObjectValues:
     479             :     case Builtins::kObjectPrototypeHasOwnProperty:
     480             :     case Builtins::kObjectPrototypeIsPrototypeOf:
     481             :     case Builtins::kObjectPrototypePropertyIsEnumerable:
     482             :     case Builtins::kObjectPrototypeToString:
     483             :     // Array builtins.
     484             :     case Builtins::kArrayConstructor:
     485             :     case Builtins::kArrayIndexOf:
     486             :     case Builtins::kArrayPrototypeValues:
     487             :     case Builtins::kArrayIncludes:
     488             :     case Builtins::kArrayPrototypeEntries:
     489             :     case Builtins::kArrayPrototypeKeys:
     490             :     case Builtins::kArrayForEach:
     491             :     case Builtins::kArrayEvery:
     492             :     case Builtins::kArraySome:
     493             :     case Builtins::kArrayReduce:
     494             :     case Builtins::kArrayReduceRight:
     495             :     // Boolean bulitins.
     496             :     case Builtins::kBooleanConstructor:
     497             :     case Builtins::kBooleanPrototypeToString:
     498             :     case Builtins::kBooleanPrototypeValueOf:
     499             :     // Date builtins.
     500             :     case Builtins::kDateConstructor:
     501             :     case Builtins::kDateNow:
     502             :     case Builtins::kDateParse:
     503             :     case Builtins::kDatePrototypeGetDate:
     504             :     case Builtins::kDatePrototypeGetDay:
     505             :     case Builtins::kDatePrototypeGetFullYear:
     506             :     case Builtins::kDatePrototypeGetHours:
     507             :     case Builtins::kDatePrototypeGetMilliseconds:
     508             :     case Builtins::kDatePrototypeGetMinutes:
     509             :     case Builtins::kDatePrototypeGetMonth:
     510             :     case Builtins::kDatePrototypeGetSeconds:
     511             :     case Builtins::kDatePrototypeGetTime:
     512             :     case Builtins::kDatePrototypeGetTimezoneOffset:
     513             :     case Builtins::kDatePrototypeGetUTCDate:
     514             :     case Builtins::kDatePrototypeGetUTCDay:
     515             :     case Builtins::kDatePrototypeGetUTCFullYear:
     516             :     case Builtins::kDatePrototypeGetUTCHours:
     517             :     case Builtins::kDatePrototypeGetUTCMilliseconds:
     518             :     case Builtins::kDatePrototypeGetUTCMinutes:
     519             :     case Builtins::kDatePrototypeGetUTCMonth:
     520             :     case Builtins::kDatePrototypeGetUTCSeconds:
     521             :     case Builtins::kDatePrototypeGetYear:
     522             :     case Builtins::kDatePrototypeToDateString:
     523             :     case Builtins::kDatePrototypeToISOString:
     524             :     case Builtins::kDatePrototypeToUTCString:
     525             :     case Builtins::kDatePrototypeToString:
     526             :     case Builtins::kDatePrototypeToTimeString:
     527             :     case Builtins::kDatePrototypeToJson:
     528             :     case Builtins::kDatePrototypeToPrimitive:
     529             :     case Builtins::kDatePrototypeValueOf:
     530             :     // Map builtins.
     531             :     case Builtins::kMapConstructor:
     532             :     case Builtins::kMapPrototypeGet:
     533             :     case Builtins::kMapPrototypeEntries:
     534             :     case Builtins::kMapPrototypeGetSize:
     535             :     case Builtins::kMapPrototypeKeys:
     536             :     case Builtins::kMapPrototypeValues:
     537             :     // Math builtins.
     538             :     case Builtins::kMathAbs:
     539             :     case Builtins::kMathAcos:
     540             :     case Builtins::kMathAcosh:
     541             :     case Builtins::kMathAsin:
     542             :     case Builtins::kMathAsinh:
     543             :     case Builtins::kMathAtan:
     544             :     case Builtins::kMathAtanh:
     545             :     case Builtins::kMathAtan2:
     546             :     case Builtins::kMathCeil:
     547             :     case Builtins::kMathCbrt:
     548             :     case Builtins::kMathExpm1:
     549             :     case Builtins::kMathClz32:
     550             :     case Builtins::kMathCos:
     551             :     case Builtins::kMathCosh:
     552             :     case Builtins::kMathExp:
     553             :     case Builtins::kMathFloor:
     554             :     case Builtins::kMathFround:
     555             :     case Builtins::kMathHypot:
     556             :     case Builtins::kMathImul:
     557             :     case Builtins::kMathLog:
     558             :     case Builtins::kMathLog1p:
     559             :     case Builtins::kMathLog2:
     560             :     case Builtins::kMathLog10:
     561             :     case Builtins::kMathMax:
     562             :     case Builtins::kMathMin:
     563             :     case Builtins::kMathPow:
     564             :     case Builtins::kMathRandom:
     565             :     case Builtins::kMathRound:
     566             :     case Builtins::kMathSign:
     567             :     case Builtins::kMathSin:
     568             :     case Builtins::kMathSinh:
     569             :     case Builtins::kMathSqrt:
     570             :     case Builtins::kMathTan:
     571             :     case Builtins::kMathTanh:
     572             :     case Builtins::kMathTrunc:
     573             :     // Number builtins.
     574             :     case Builtins::kNumberConstructor:
     575             :     case Builtins::kNumberIsFinite:
     576             :     case Builtins::kNumberIsInteger:
     577             :     case Builtins::kNumberIsNaN:
     578             :     case Builtins::kNumberIsSafeInteger:
     579             :     case Builtins::kNumberParseFloat:
     580             :     case Builtins::kNumberParseInt:
     581             :     case Builtins::kNumberPrototypeToExponential:
     582             :     case Builtins::kNumberPrototypeToFixed:
     583             :     case Builtins::kNumberPrototypeToPrecision:
     584             :     case Builtins::kNumberPrototypeToString:
     585             :     case Builtins::kNumberPrototypeValueOf:
     586             :     // Set builtins.
     587             :     case Builtins::kSetConstructor:
     588             :     case Builtins::kSetPrototypeEntries:
     589             :     case Builtins::kSetPrototypeGetSize:
     590             :     case Builtins::kSetPrototypeValues:
     591             :     // String builtins. Strings are immutable.
     592             :     case Builtins::kStringFromCharCode:
     593             :     case Builtins::kStringFromCodePoint:
     594             :     case Builtins::kStringConstructor:
     595             :     case Builtins::kStringPrototypeAnchor:
     596             :     case Builtins::kStringPrototypeBig:
     597             :     case Builtins::kStringPrototypeBlink:
     598             :     case Builtins::kStringPrototypeBold:
     599             :     case Builtins::kStringPrototypeCharAt:
     600             :     case Builtins::kStringPrototypeCharCodeAt:
     601             :     case Builtins::kStringPrototypeCodePointAt:
     602             :     case Builtins::kStringPrototypeConcat:
     603             :     case Builtins::kStringPrototypeEndsWith:
     604             :     case Builtins::kStringPrototypeFixed:
     605             :     case Builtins::kStringPrototypeFontcolor:
     606             :     case Builtins::kStringPrototypeFontsize:
     607             :     case Builtins::kStringPrototypeIncludes:
     608             :     case Builtins::kStringPrototypeIndexOf:
     609             :     case Builtins::kStringPrototypeItalics:
     610             :     case Builtins::kStringPrototypeLastIndexOf:
     611             :     case Builtins::kStringPrototypeLink:
     612             :     case Builtins::kStringPrototypePadEnd:
     613             :     case Builtins::kStringPrototypePadStart:
     614             :     case Builtins::kStringPrototypeRepeat:
     615             :     case Builtins::kStringPrototypeSlice:
     616             :     case Builtins::kStringPrototypeSmall:
     617             :     case Builtins::kStringPrototypeStartsWith:
     618             :     case Builtins::kStringPrototypeStrike:
     619             :     case Builtins::kStringPrototypeSub:
     620             :     case Builtins::kStringPrototypeSubstr:
     621             :     case Builtins::kStringPrototypeSubstring:
     622             :     case Builtins::kStringPrototypeSup:
     623             :     case Builtins::kStringPrototypeToString:
     624             : #ifndef V8_INTL_SUPPORT
     625             :     case Builtins::kStringPrototypeToLowerCase:
     626             :     case Builtins::kStringPrototypeToUpperCase:
     627             : #endif
     628             :     case Builtins::kStringPrototypeTrim:
     629             :     case Builtins::kStringPrototypeTrimLeft:
     630             :     case Builtins::kStringPrototypeTrimRight:
     631             :     case Builtins::kStringPrototypeValueOf:
     632             :     case Builtins::kStringToNumber:
     633             :     case Builtins::kSubString:
     634             :     // Symbol builtins.
     635             :     case Builtins::kSymbolConstructor:
     636             :     case Builtins::kSymbolKeyFor:
     637             :     case Builtins::kSymbolPrototypeToString:
     638             :     case Builtins::kSymbolPrototypeValueOf:
     639             :     case Builtins::kSymbolPrototypeToPrimitive:
     640             :     // JSON builtins.
     641             :     case Builtins::kJsonParse:
     642             :     case Builtins::kJsonStringify:
     643             :     // Global function builtins.
     644             :     case Builtins::kGlobalDecodeURI:
     645             :     case Builtins::kGlobalDecodeURIComponent:
     646             :     case Builtins::kGlobalEncodeURI:
     647             :     case Builtins::kGlobalEncodeURIComponent:
     648             :     case Builtins::kGlobalEscape:
     649             :     case Builtins::kGlobalUnescape:
     650             :     case Builtins::kGlobalIsFinite:
     651             :     case Builtins::kGlobalIsNaN:
     652             :     // Error builtins.
     653             :     case Builtins::kMakeError:
     654             :     case Builtins::kMakeTypeError:
     655             :     case Builtins::kMakeSyntaxError:
     656             :     case Builtins::kMakeRangeError:
     657             :     case Builtins::kMakeURIError:
     658             :       return true;
     659             :     default:
     660        1994 :       if (FLAG_trace_side_effect_free_debug_evaluate) {
     661             :         PrintF("[debug-evaluate] built-in %s may cause side effect.\n",
     662           0 :                Builtins::name(id));
     663             :       }
     664             :       return false;
     665             :   }
     666             : }
     667             : 
     668             : static const Address accessors_with_no_side_effect[] = {
     669             :     // Whitelist for accessors.
     670             :     FUNCTION_ADDR(Accessors::StringLengthGetter),
     671             :     FUNCTION_ADDR(Accessors::ArrayLengthGetter),
     672             :     FUNCTION_ADDR(Accessors::FunctionLengthGetter),
     673             :     FUNCTION_ADDR(Accessors::FunctionNameGetter),
     674             :     FUNCTION_ADDR(Accessors::BoundFunctionLengthGetter),
     675             :     FUNCTION_ADDR(Accessors::BoundFunctionNameGetter),
     676             : };
     677             : 
     678             : }  // anonymous namespace
     679             : 
     680             : // static
     681        8181 : bool DebugEvaluate::FunctionHasNoSideEffect(Handle<SharedFunctionInfo> info) {
     682        8181 :   if (FLAG_trace_side_effect_free_debug_evaluate) {
     683             :     PrintF("[debug-evaluate] Checking function %s for side effect.\n",
     684           0 :            info->DebugName()->ToCString().get());
     685             :   }
     686             : 
     687             :   DCHECK(info->is_compiled());
     688             : 
     689        8181 :   if (info->HasBytecodeArray()) {
     690             :     // Check bytecodes against whitelist.
     691             :     Handle<BytecodeArray> bytecode_array(info->bytecode_array());
     692        4437 :     if (FLAG_trace_side_effect_free_debug_evaluate) bytecode_array->Print();
     693       72981 :     for (interpreter::BytecodeArrayIterator it(bytecode_array); !it.done();
     694       64107 :          it.Advance()) {
     695       64959 :       interpreter::Bytecode bytecode = it.current_bytecode();
     696             : 
     697       64959 :       if (interpreter::Bytecodes::IsCallRuntime(bytecode)) {
     698             :         Runtime::FunctionId id =
     699             :             (bytecode == interpreter::Bytecode::kInvokeIntrinsic)
     700             :                 ? it.GetIntrinsicIdOperand(0)
     701        2259 :                 : it.GetRuntimeIdOperand(0);
     702        2259 :         if (IntrinsicHasNoSideEffect(id)) continue;
     703         852 :         return false;
     704             :       }
     705             : 
     706       62700 :       if (BytecodeHasNoSideEffect(bytecode)) continue;
     707             : 
     708             :       // Did not match whitelist.
     709             :       return false;
     710             :     }
     711        3585 :     return true;
     712             :   } else {
     713             :     // Check built-ins against whitelist.
     714             :     int builtin_index = info->HasLazyDeserializationBuiltinId()
     715             :                             ? info->lazy_deserialization_builtin_id()
     716        3744 :                             : info->code()->builtin_index();
     717             :     DCHECK_NE(Builtins::kDeserializeLazy, builtin_index);
     718        7488 :     if (builtin_index >= 0 && builtin_index < Builtins::builtin_count &&
     719        3744 :         BuiltinHasNoSideEffect(static_cast<Builtins::Name>(builtin_index))) {
     720             : #ifdef DEBUG
     721             :       if (info->code()->builtin_index() == Builtins::kDeserializeLazy) {
     722             :         return true;  // Target builtin is not yet deserialized.
     723             :       }
     724             :       // TODO(yangguo): Check builtin-to-builtin calls too.
     725             :       int mode = RelocInfo::ModeMask(RelocInfo::EXTERNAL_REFERENCE);
     726             :       bool failed = false;
     727             :       for (RelocIterator it(info->code(), mode); !it.done(); it.next()) {
     728             :         RelocInfo* rinfo = it.rinfo();
     729             :         Address address = rinfo->target_external_reference();
     730             :         const Runtime::Function* function = Runtime::FunctionForEntry(address);
     731             :         if (function == nullptr) continue;
     732             :         if (!IntrinsicHasNoSideEffect(function->function_id)) {
     733             :           PrintF("Whitelisted builtin %s calls non-whitelisted intrinsic %s\n",
     734             :                  Builtins::name(builtin_index), function->name);
     735             :           failed = true;
     736             :         }
     737             :         DCHECK(!failed);
     738             :       }
     739             : #endif  // DEBUG
     740             :       return true;
     741             :     }
     742             :   }
     743             : 
     744        1994 :   return false;
     745             : }
     746             : 
     747             : // static
     748          70 : bool DebugEvaluate::CallbackHasNoSideEffect(Address function_addr) {
     749         259 :   for (size_t i = 0; i < arraysize(accessors_with_no_side_effect); i++) {
     750         250 :     if (function_addr == accessors_with_no_side_effect[i]) return true;
     751             :   }
     752             : 
     753           9 :   if (FLAG_trace_side_effect_free_debug_evaluate) {
     754             :     PrintF("[debug-evaluate] API Callback at %p may cause side effect.\n",
     755           0 :            reinterpret_cast<void*>(function_addr));
     756             :   }
     757             :   return false;
     758             : }
     759             : 
     760             : }  // namespace internal
     761             : }  // namespace v8

Generated by: LCOV version 1.10