• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/compiler.h"
9 #include "src/contexts.h"
10 #include "src/debug/debug-frames.h"
11 #include "src/debug/debug-scopes.h"
12 #include "src/debug/debug.h"
13 #include "src/frames-inl.h"
14 #include "src/globals.h"
15 #include "src/interpreter/bytecode-array-iterator.h"
16 #include "src/interpreter/bytecodes.h"
17 #include "src/isolate-inl.h"
18 
19 namespace v8 {
20 namespace internal {
21 
IsDebugContext(Isolate * isolate,Context * context)22 static inline bool IsDebugContext(Isolate* isolate, Context* context) {
23   return context->native_context() == *isolate->debug()->debug_context();
24 }
25 
Global(Isolate * isolate,Handle<String> source)26 MaybeHandle<Object> DebugEvaluate::Global(Isolate* isolate,
27                                           Handle<String> source) {
28   // Handle the processing of break.
29   DisableBreak disable_break_scope(isolate->debug());
30 
31   // Enter the top context from before the debugger was invoked.
32   SaveContext save(isolate);
33   SaveContext* top = &save;
34   while (top != NULL && IsDebugContext(isolate, *top->context())) {
35     top = top->prev();
36   }
37   if (top != NULL) isolate->set_context(*top->context());
38 
39   // Get the native context now set to the top context from before the
40   // debugger was invoked.
41   Handle<Context> context = isolate->native_context();
42   Handle<JSObject> receiver(context->global_proxy());
43   Handle<SharedFunctionInfo> outer_info(context->closure()->shared(), isolate);
44   return Evaluate(isolate, outer_info, context, receiver, source, false);
45 }
46 
Local(Isolate * isolate,StackFrame::Id frame_id,int inlined_jsframe_index,Handle<String> source,bool throw_on_side_effect)47 MaybeHandle<Object> DebugEvaluate::Local(Isolate* isolate,
48                                          StackFrame::Id frame_id,
49                                          int inlined_jsframe_index,
50                                          Handle<String> source,
51                                          bool throw_on_side_effect) {
52   // Handle the processing of break.
53   DisableBreak disable_break_scope(isolate->debug());
54 
55   // Get the frame where the debugging is performed.
56   StackTraceFrameIterator it(isolate, frame_id);
57   if (!it.is_javascript()) return isolate->factory()->undefined_value();
58   JavaScriptFrame* frame = it.javascript_frame();
59 
60   // Traverse the saved contexts chain to find the active context for the
61   // selected frame.
62   SaveContext* save =
63       DebugFrameHelper::FindSavedContextForFrame(isolate, frame);
64   SaveContext savex(isolate);
65   isolate->set_context(*(save->context()));
66 
67   // This is not a lot different than DebugEvaluate::Global, except that
68   // variables accessible by the function we are evaluating from are
69   // materialized and included on top of the native context. Changes to
70   // the materialized object are written back afterwards.
71   // Note that the native context is taken from the original context chain,
72   // which may not be the current native context of the isolate.
73   ContextBuilder context_builder(isolate, frame, inlined_jsframe_index);
74   if (isolate->has_pending_exception()) return MaybeHandle<Object>();
75 
76   Handle<Context> context = context_builder.evaluation_context();
77   Handle<JSObject> receiver(context->global_proxy());
78   MaybeHandle<Object> maybe_result =
79       Evaluate(isolate, context_builder.outer_info(), context, receiver, source,
80                throw_on_side_effect);
81   if (!maybe_result.is_null()) context_builder.UpdateValues();
82   return maybe_result;
83 }
84 
85 
86 // Compile and evaluate source for the given context.
Evaluate(Isolate * isolate,Handle<SharedFunctionInfo> outer_info,Handle<Context> context,Handle<Object> receiver,Handle<String> source,bool throw_on_side_effect)87 MaybeHandle<Object> DebugEvaluate::Evaluate(
88     Isolate* isolate, Handle<SharedFunctionInfo> outer_info,
89     Handle<Context> context, Handle<Object> receiver, Handle<String> source,
90     bool throw_on_side_effect) {
91   Handle<JSFunction> eval_fun;
92   ASSIGN_RETURN_ON_EXCEPTION(
93       isolate, eval_fun,
94       Compiler::GetFunctionFromEval(source, outer_info, context, SLOPPY,
95                                     NO_PARSE_RESTRICTION, kNoSourcePosition,
96                                     kNoSourcePosition, kNoSourcePosition),
97       Object);
98 
99   Handle<Object> result;
100   {
101     NoSideEffectScope no_side_effect(isolate, throw_on_side_effect);
102     ASSIGN_RETURN_ON_EXCEPTION(
103         isolate, result, Execution::Call(isolate, eval_fun, receiver, 0, NULL),
104         Object);
105   }
106 
107   // Skip the global proxy as it has no properties and always delegates to the
108   // real global object.
109   if (result->IsJSGlobalProxy()) {
110     PrototypeIterator iter(isolate, Handle<JSGlobalProxy>::cast(result));
111     // TODO(verwaest): This will crash when the global proxy is detached.
112     result = PrototypeIterator::GetCurrent<JSObject>(iter);
113   }
114 
115   return result;
116 }
117 
118 
ContextBuilder(Isolate * isolate,JavaScriptFrame * frame,int inlined_jsframe_index)119 DebugEvaluate::ContextBuilder::ContextBuilder(Isolate* isolate,
120                                               JavaScriptFrame* frame,
121                                               int inlined_jsframe_index)
122     : isolate_(isolate),
123       frame_(frame),
124       inlined_jsframe_index_(inlined_jsframe_index) {
125   FrameInspector frame_inspector(frame, inlined_jsframe_index, isolate);
126   Handle<JSFunction> local_function = frame_inspector.GetFunction();
127   Handle<Context> outer_context(local_function->context());
128   evaluation_context_ = outer_context;
129   outer_info_ = handle(local_function->shared());
130   Factory* factory = isolate->factory();
131 
132   // To evaluate as if we were running eval at the point of the debug break,
133   // we reconstruct the context chain as follows:
134   //  - To make stack-allocated variables visible, we materialize them and
135   //    use a debug-evaluate context to wrap both the materialized object and
136   //    the original context.
137   //  - We use the original context chain from the function context to the
138   //    native context.
139   //  - Between the function scope and the native context, we only resolve
140   //    variable names that the current function already uses. Only for these
141   //    names we can be sure that they will be correctly resolved. For the
142   //    rest, we only resolve to with, script, and native contexts. We use a
143   //    whitelist to implement that.
144   // Context::Lookup has special handling for debug-evaluate contexts:
145   //  - Look up in the materialized stack variables.
146   //  - Look up in the original context.
147   //  - Check the whitelist to find out whether to skip contexts during lookup.
148   const ScopeIterator::Option option = ScopeIterator::COLLECT_NON_LOCALS;
149   for (ScopeIterator it(isolate, &frame_inspector, option); !it.Done();
150        it.Next()) {
151     ScopeIterator::ScopeType scope_type = it.Type();
152     if (scope_type == ScopeIterator::ScopeTypeLocal) {
153       DCHECK_EQ(FUNCTION_SCOPE, it.CurrentScopeInfo()->scope_type());
154       Handle<JSObject> materialized = factory->NewJSObjectWithNullProto();
155       Handle<Context> local_context =
156           it.HasContext() ? it.CurrentContext() : outer_context;
157       Handle<StringSet> non_locals = it.GetNonLocals();
158       MaterializeReceiver(materialized, local_context, local_function,
159                           non_locals);
160       frame_inspector.MaterializeStackLocals(materialized, local_function);
161       MaterializeArgumentsObject(materialized, local_function);
162       ContextChainElement context_chain_element;
163       context_chain_element.scope_info = it.CurrentScopeInfo();
164       context_chain_element.materialized_object = materialized;
165       // Non-locals that are already being referenced by the current function
166       // are guaranteed to be correctly resolved.
167       context_chain_element.whitelist = non_locals;
168       if (it.HasContext()) {
169         context_chain_element.wrapped_context = it.CurrentContext();
170       }
171       context_chain_.Add(context_chain_element);
172       evaluation_context_ = outer_context;
173       break;
174     } else if (scope_type == ScopeIterator::ScopeTypeCatch ||
175                scope_type == ScopeIterator::ScopeTypeWith) {
176       ContextChainElement context_chain_element;
177       Handle<Context> current_context = it.CurrentContext();
178       if (!current_context->IsDebugEvaluateContext()) {
179         context_chain_element.wrapped_context = current_context;
180       }
181       context_chain_.Add(context_chain_element);
182     } else if (scope_type == ScopeIterator::ScopeTypeBlock ||
183                scope_type == ScopeIterator::ScopeTypeEval) {
184       Handle<JSObject> materialized = factory->NewJSObjectWithNullProto();
185       frame_inspector.MaterializeStackLocals(materialized,
186                                              it.CurrentScopeInfo());
187       ContextChainElement context_chain_element;
188       context_chain_element.scope_info = it.CurrentScopeInfo();
189       context_chain_element.materialized_object = materialized;
190       if (it.HasContext()) {
191         context_chain_element.wrapped_context = it.CurrentContext();
192       }
193       context_chain_.Add(context_chain_element);
194     } else {
195       break;
196     }
197   }
198 
199   for (int i = context_chain_.length() - 1; i >= 0; i--) {
200     Handle<ScopeInfo> scope_info(ScopeInfo::CreateForWithScope(
201         isolate, evaluation_context_->IsNativeContext()
202                      ? Handle<ScopeInfo>::null()
203                      : Handle<ScopeInfo>(evaluation_context_->scope_info())));
204     scope_info->SetIsDebugEvaluateScope();
205     evaluation_context_ = factory->NewDebugEvaluateContext(
206         evaluation_context_, scope_info, context_chain_[i].materialized_object,
207         context_chain_[i].wrapped_context, context_chain_[i].whitelist);
208   }
209 }
210 
211 
UpdateValues()212 void DebugEvaluate::ContextBuilder::UpdateValues() {
213   // TODO(yangguo): remove updating values.
214   for (int i = 0; i < context_chain_.length(); i++) {
215     ContextChainElement element = context_chain_[i];
216     if (!element.materialized_object.is_null()) {
217       // Write back potential changes to materialized stack locals to the stack.
218       FrameInspector(frame_, inlined_jsframe_index_, isolate_)
219           .UpdateStackLocalsFromMaterializedObject(element.materialized_object,
220                                                    element.scope_info);
221     }
222   }
223 }
224 
225 
MaterializeArgumentsObject(Handle<JSObject> target,Handle<JSFunction> function)226 void DebugEvaluate::ContextBuilder::MaterializeArgumentsObject(
227     Handle<JSObject> target, Handle<JSFunction> function) {
228   // Do not materialize the arguments object for eval or top-level code.
229   // Skip if "arguments" is already taken.
230   if (function->shared()->is_toplevel()) return;
231   Maybe<bool> maybe = JSReceiver::HasOwnProperty(
232       target, isolate_->factory()->arguments_string());
233   DCHECK(maybe.IsJust());
234   if (maybe.FromJust()) return;
235 
236   // FunctionGetArguments can't throw an exception.
237   Handle<JSObject> arguments = Accessors::FunctionGetArguments(function);
238   Handle<String> arguments_str = isolate_->factory()->arguments_string();
239   JSObject::SetOwnPropertyIgnoreAttributes(target, arguments_str, arguments,
240                                            NONE)
241       .Check();
242 }
243 
MaterializeReceiver(Handle<JSObject> target,Handle<Context> local_context,Handle<JSFunction> local_function,Handle<StringSet> non_locals)244 void DebugEvaluate::ContextBuilder::MaterializeReceiver(
245     Handle<JSObject> target, Handle<Context> local_context,
246     Handle<JSFunction> local_function, Handle<StringSet> non_locals) {
247   Handle<Object> recv = isolate_->factory()->undefined_value();
248   Handle<String> name = isolate_->factory()->this_string();
249   if (non_locals->Has(name)) {
250     // 'this' is allocated in an outer context and is is already being
251     // referenced by the current function, so it can be correctly resolved.
252     return;
253   } else if (local_function->shared()->scope_info()->HasReceiver() &&
254              !frame_->receiver()->IsTheHole(isolate_)) {
255     recv = handle(frame_->receiver(), isolate_);
256   }
257   JSObject::SetOwnPropertyIgnoreAttributes(target, name, recv, NONE).Check();
258 }
259 
260 namespace {
261 
IntrinsicHasNoSideEffect(Runtime::FunctionId id)262 bool IntrinsicHasNoSideEffect(Runtime::FunctionId id) {
263   switch (id) {
264     // Whitelist for intrinsics amd runtime functions.
265     // Conversions.
266     case Runtime::kToInteger:
267     case Runtime::kInlineToInteger:
268     case Runtime::kToObject:
269     case Runtime::kInlineToObject:
270     case Runtime::kToString:
271     case Runtime::kInlineToString:
272     case Runtime::kToLength:
273     case Runtime::kInlineToLength:
274     case Runtime::kToNumber:
275     // Type checks.
276     case Runtime::kIsJSReceiver:
277     case Runtime::kInlineIsJSReceiver:
278     case Runtime::kIsSmi:
279     case Runtime::kInlineIsSmi:
280     case Runtime::kIsArray:
281     case Runtime::kInlineIsArray:
282     case Runtime::kIsFunction:
283     case Runtime::kIsDate:
284     case Runtime::kIsJSProxy:
285     case Runtime::kIsRegExp:
286     case Runtime::kIsTypedArray:
287     // Loads.
288     case Runtime::kLoadLookupSlotForCall:
289     // Arrays.
290     case Runtime::kArraySpeciesConstructor:
291     case Runtime::kNormalizeElements:
292     case Runtime::kGetArrayKeys:
293     case Runtime::kHasComplexElements:
294     case Runtime::kEstimateNumberOfElements:
295     // Errors.
296     case Runtime::kReThrow:
297     case Runtime::kThrowReferenceError:
298     case Runtime::kThrowSymbolIteratorInvalid:
299     case Runtime::kThrowIteratorResultNotAnObject:
300     case Runtime::kNewTypeError:
301     // Strings.
302     case Runtime::kInlineStringCharCodeAt:
303     case Runtime::kStringCharCodeAt:
304     case Runtime::kStringIndexOf:
305     case Runtime::kStringReplaceOneCharWithString:
306     case Runtime::kSubString:
307     case Runtime::kInlineSubString:
308     case Runtime::kRegExpInternalReplace:
309     // Literals.
310     case Runtime::kCreateArrayLiteral:
311     case Runtime::kCreateObjectLiteral:
312     case Runtime::kCreateRegExpLiteral:
313     // Misc.
314     case Runtime::kForInPrepare:
315     case Runtime::kInlineCall:
316     case Runtime::kCall:
317     case Runtime::kInlineMaxSmi:
318     case Runtime::kMaxSmi:
319       return true;
320     default:
321       if (FLAG_trace_side_effect_free_debug_evaluate) {
322         PrintF("[debug-evaluate] intrinsic %s may cause side effect.\n",
323                Runtime::FunctionForId(id)->name);
324       }
325       return false;
326   }
327 }
328 
BytecodeHasNoSideEffect(interpreter::Bytecode bytecode)329 bool BytecodeHasNoSideEffect(interpreter::Bytecode bytecode) {
330   typedef interpreter::Bytecode Bytecode;
331   typedef interpreter::Bytecodes Bytecodes;
332   if (Bytecodes::IsWithoutExternalSideEffects(bytecode)) return true;
333   if (Bytecodes::IsCallOrConstruct(bytecode)) return true;
334   if (Bytecodes::WritesBooleanToAccumulator(bytecode)) return true;
335   if (Bytecodes::IsJumpIfToBoolean(bytecode)) return true;
336   if (Bytecodes::IsPrefixScalingBytecode(bytecode)) return true;
337   switch (bytecode) {
338     // Whitelist for bytecodes.
339     // Loads.
340     case Bytecode::kLdaLookupSlot:
341     case Bytecode::kLdaGlobal:
342     case Bytecode::kLdaNamedProperty:
343     case Bytecode::kLdaKeyedProperty:
344     // Arithmetics.
345     case Bytecode::kAdd:
346     case Bytecode::kAddSmi:
347     case Bytecode::kSub:
348     case Bytecode::kSubSmi:
349     case Bytecode::kMul:
350     case Bytecode::kDiv:
351     case Bytecode::kMod:
352     case Bytecode::kBitwiseAnd:
353     case Bytecode::kBitwiseAndSmi:
354     case Bytecode::kBitwiseOr:
355     case Bytecode::kBitwiseOrSmi:
356     case Bytecode::kBitwiseXor:
357     case Bytecode::kShiftLeft:
358     case Bytecode::kShiftLeftSmi:
359     case Bytecode::kShiftRight:
360     case Bytecode::kShiftRightSmi:
361     case Bytecode::kShiftRightLogical:
362     case Bytecode::kInc:
363     case Bytecode::kDec:
364     case Bytecode::kLogicalNot:
365     case Bytecode::kToBooleanLogicalNot:
366     case Bytecode::kTypeOf:
367     // Contexts.
368     case Bytecode::kCreateBlockContext:
369     case Bytecode::kCreateCatchContext:
370     case Bytecode::kCreateFunctionContext:
371     case Bytecode::kCreateEvalContext:
372     case Bytecode::kCreateWithContext:
373     // Literals.
374     case Bytecode::kCreateArrayLiteral:
375     case Bytecode::kCreateObjectLiteral:
376     case Bytecode::kCreateRegExpLiteral:
377     // Allocations.
378     case Bytecode::kCreateClosure:
379     case Bytecode::kCreateUnmappedArguments:
380     // Conversions.
381     case Bytecode::kToObject:
382     case Bytecode::kToNumber:
383     // Misc.
384     case Bytecode::kForInPrepare:
385     case Bytecode::kForInContinue:
386     case Bytecode::kForInNext:
387     case Bytecode::kForInStep:
388     case Bytecode::kThrow:
389     case Bytecode::kReThrow:
390     case Bytecode::kIllegal:
391     case Bytecode::kCallJSRuntime:
392     case Bytecode::kStackCheck:
393     case Bytecode::kReturn:
394     case Bytecode::kSetPendingMessage:
395       return true;
396     default:
397       if (FLAG_trace_side_effect_free_debug_evaluate) {
398         PrintF("[debug-evaluate] bytecode %s may cause side effect.\n",
399                Bytecodes::ToString(bytecode));
400       }
401       return false;
402   }
403 }
404 
BuiltinHasNoSideEffect(Builtins::Name id)405 bool BuiltinHasNoSideEffect(Builtins::Name id) {
406   switch (id) {
407     // Whitelist for builtins.
408     // Array builtins.
409     case Builtins::kArrayCode:
410     case Builtins::kArrayIndexOf:
411     case Builtins::kArrayPrototypeValues:
412     case Builtins::kArrayIncludes:
413     case Builtins::kArrayPrototypeEntries:
414     case Builtins::kArrayPrototypeKeys:
415     case Builtins::kArrayForEach:
416     // Math builtins.
417     case Builtins::kMathAbs:
418     case Builtins::kMathAcos:
419     case Builtins::kMathAcosh:
420     case Builtins::kMathAsin:
421     case Builtins::kMathAsinh:
422     case Builtins::kMathAtan:
423     case Builtins::kMathAtanh:
424     case Builtins::kMathAtan2:
425     case Builtins::kMathCeil:
426     case Builtins::kMathCbrt:
427     case Builtins::kMathExpm1:
428     case Builtins::kMathClz32:
429     case Builtins::kMathCos:
430     case Builtins::kMathCosh:
431     case Builtins::kMathExp:
432     case Builtins::kMathFloor:
433     case Builtins::kMathFround:
434     case Builtins::kMathHypot:
435     case Builtins::kMathImul:
436     case Builtins::kMathLog:
437     case Builtins::kMathLog1p:
438     case Builtins::kMathLog2:
439     case Builtins::kMathLog10:
440     case Builtins::kMathMax:
441     case Builtins::kMathMin:
442     case Builtins::kMathPow:
443     case Builtins::kMathRandom:
444     case Builtins::kMathRound:
445     case Builtins::kMathSign:
446     case Builtins::kMathSin:
447     case Builtins::kMathSinh:
448     case Builtins::kMathSqrt:
449     case Builtins::kMathTan:
450     case Builtins::kMathTanh:
451     case Builtins::kMathTrunc:
452     // Number builtins.
453     case Builtins::kNumberConstructor:
454     case Builtins::kNumberIsFinite:
455     case Builtins::kNumberIsInteger:
456     case Builtins::kNumberIsNaN:
457     case Builtins::kNumberIsSafeInteger:
458     case Builtins::kNumberParseFloat:
459     case Builtins::kNumberParseInt:
460     case Builtins::kNumberPrototypeToExponential:
461     case Builtins::kNumberPrototypeToFixed:
462     case Builtins::kNumberPrototypeToPrecision:
463     case Builtins::kNumberPrototypeToString:
464     case Builtins::kNumberPrototypeValueOf:
465     // String builtins. Strings are immutable.
466     case Builtins::kStringFromCharCode:
467     case Builtins::kStringFromCodePoint:
468     case Builtins::kStringConstructor:
469     case Builtins::kStringPrototypeCharAt:
470     case Builtins::kStringPrototypeCharCodeAt:
471     case Builtins::kStringPrototypeEndsWith:
472     case Builtins::kStringPrototypeIncludes:
473     case Builtins::kStringPrototypeIndexOf:
474     case Builtins::kStringPrototypeLastIndexOf:
475     case Builtins::kStringPrototypeStartsWith:
476     case Builtins::kStringPrototypeSubstr:
477     case Builtins::kStringPrototypeSubstring:
478     case Builtins::kStringPrototypeToString:
479     case Builtins::kStringPrototypeToLowerCase:
480     case Builtins::kStringPrototypeToUpperCase:
481     case Builtins::kStringPrototypeTrim:
482     case Builtins::kStringPrototypeTrimLeft:
483     case Builtins::kStringPrototypeTrimRight:
484     case Builtins::kStringPrototypeValueOf:
485     // JSON builtins.
486     case Builtins::kJsonParse:
487     case Builtins::kJsonStringify:
488     // Error builtins.
489     case Builtins::kMakeError:
490     case Builtins::kMakeTypeError:
491     case Builtins::kMakeSyntaxError:
492     case Builtins::kMakeRangeError:
493     case Builtins::kMakeURIError:
494       return true;
495     default:
496       if (FLAG_trace_side_effect_free_debug_evaluate) {
497         PrintF("[debug-evaluate] built-in %s may cause side effect.\n",
498                Builtins::name(id));
499       }
500       return false;
501   }
502 }
503 
504 static const Address accessors_with_no_side_effect[] = {
505     // Whitelist for accessors.
506     FUNCTION_ADDR(Accessors::StringLengthGetter),
507     FUNCTION_ADDR(Accessors::ArrayLengthGetter)};
508 
509 }  // anonymous namespace
510 
511 // static
FunctionHasNoSideEffect(Handle<SharedFunctionInfo> info)512 bool DebugEvaluate::FunctionHasNoSideEffect(Handle<SharedFunctionInfo> info) {
513   if (FLAG_trace_side_effect_free_debug_evaluate) {
514     PrintF("[debug-evaluate] Checking function %s for side effect.\n",
515            info->DebugName()->ToCString().get());
516   }
517 
518   DCHECK(info->is_compiled());
519 
520   if (info->HasBytecodeArray()) {
521     // Check bytecodes against whitelist.
522     Handle<BytecodeArray> bytecode_array(info->bytecode_array());
523     if (FLAG_trace_side_effect_free_debug_evaluate) bytecode_array->Print();
524     for (interpreter::BytecodeArrayIterator it(bytecode_array); !it.done();
525          it.Advance()) {
526       interpreter::Bytecode bytecode = it.current_bytecode();
527 
528       if (interpreter::Bytecodes::IsCallRuntime(bytecode)) {
529         Runtime::FunctionId id =
530             (bytecode == interpreter::Bytecode::kInvokeIntrinsic)
531                 ? it.GetIntrinsicIdOperand(0)
532                 : it.GetRuntimeIdOperand(0);
533         if (IntrinsicHasNoSideEffect(id)) continue;
534         return false;
535       }
536 
537       if (BytecodeHasNoSideEffect(bytecode)) continue;
538 
539       // Did not match whitelist.
540       return false;
541     }
542     return true;
543   } else {
544     // Check built-ins against whitelist.
545     int builtin_index = info->code()->builtin_index();
546     if (builtin_index >= 0 && builtin_index < Builtins::builtin_count &&
547         BuiltinHasNoSideEffect(static_cast<Builtins::Name>(builtin_index))) {
548       return true;
549     }
550   }
551 
552   return false;
553 }
554 
555 // static
CallbackHasNoSideEffect(Address function_addr)556 bool DebugEvaluate::CallbackHasNoSideEffect(Address function_addr) {
557   for (size_t i = 0; i < arraysize(accessors_with_no_side_effect); i++) {
558     if (function_addr == accessors_with_no_side_effect[i]) return true;
559   }
560 
561   if (FLAG_trace_side_effect_free_debug_evaluate) {
562     PrintF("[debug-evaluate] API Callback at %p may cause side effect.\n",
563            reinterpret_cast<void*>(function_addr));
564   }
565   return false;
566 }
567 
568 }  // namespace internal
569 }  // namespace v8
570