• 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/builtins/accessors.h"
8 #include "src/codegen/assembler-inl.h"
9 #include "src/codegen/compiler.h"
10 #include "src/common/globals.h"
11 #include "src/debug/debug-frames.h"
12 #include "src/debug/debug-scopes.h"
13 #include "src/debug/debug.h"
14 #include "src/execution/frames-inl.h"
15 #include "src/execution/isolate-inl.h"
16 #include "src/interpreter/bytecode-array-iterator.h"
17 #include "src/interpreter/bytecodes.h"
18 #include "src/objects/contexts.h"
19 #include "src/snapshot/snapshot.h"
20 #include "src/wasm/wasm-debug.h"
21 #include "src/wasm/wasm-js.h"
22 
23 namespace v8 {
24 namespace internal {
25 
26 namespace {
GetFunctionInfo(Isolate * isolate,Handle<String> source,REPLMode repl_mode)27 static MaybeHandle<SharedFunctionInfo> GetFunctionInfo(Isolate* isolate,
28                                                        Handle<String> source,
29                                                        REPLMode repl_mode) {
30   Compiler::ScriptDetails script_details(isolate->factory()->empty_string());
31   script_details.repl_mode = repl_mode;
32   ScriptOriginOptions origin_options(false, true);
33   return Compiler::GetSharedFunctionInfoForScript(
34       isolate, source, script_details, origin_options, nullptr, nullptr,
35       ScriptCompiler::kNoCompileOptions, ScriptCompiler::kNoCacheNoReason,
36       NOT_NATIVES_CODE);
37 }
38 }  // namespace
39 
Global(Isolate * isolate,Handle<String> source,debug::EvaluateGlobalMode mode,REPLMode repl_mode)40 MaybeHandle<Object> DebugEvaluate::Global(Isolate* isolate,
41                                           Handle<String> source,
42                                           debug::EvaluateGlobalMode mode,
43                                           REPLMode repl_mode) {
44   // Disable breaks in side-effect free mode.
45   DisableBreak disable_break_scope(
46       isolate->debug(),
47       mode == debug::EvaluateGlobalMode::kDisableBreaks ||
48           mode ==
49               debug::EvaluateGlobalMode::kDisableBreaksAndThrowOnSideEffect);
50 
51   Handle<SharedFunctionInfo> shared_info;
52   if (!GetFunctionInfo(isolate, source, repl_mode).ToHandle(&shared_info)) {
53     return MaybeHandle<Object>();
54   }
55 
56   Handle<Context> context = isolate->native_context();
57   Handle<JSFunction> fun =
58       isolate->factory()->NewFunctionFromSharedFunctionInfo(shared_info,
59                                                             context);
60   if (mode == debug::EvaluateGlobalMode::kDisableBreaksAndThrowOnSideEffect) {
61     isolate->debug()->StartSideEffectCheckMode();
62   }
63   MaybeHandle<Object> result = Execution::Call(
64       isolate, fun, Handle<JSObject>(context->global_proxy(), isolate), 0,
65       nullptr);
66   if (mode == debug::EvaluateGlobalMode::kDisableBreaksAndThrowOnSideEffect) {
67     isolate->debug()->StopSideEffectCheckMode();
68   }
69   return result;
70 }
71 
Local(Isolate * isolate,StackFrameId frame_id,int inlined_jsframe_index,Handle<String> source,bool throw_on_side_effect)72 MaybeHandle<Object> DebugEvaluate::Local(Isolate* isolate,
73                                          StackFrameId frame_id,
74                                          int inlined_jsframe_index,
75                                          Handle<String> source,
76                                          bool throw_on_side_effect) {
77   // Handle the processing of break.
78   DisableBreak disable_break_scope(isolate->debug());
79 
80   // Get the frame where the debugging is performed.
81   StackTraceFrameIterator it(isolate, frame_id);
82   if (!it.is_javascript()) return isolate->factory()->undefined_value();
83   JavaScriptFrame* frame = it.javascript_frame();
84 
85   // This is not a lot different than DebugEvaluate::Global, except that
86   // variables accessible by the function we are evaluating from are
87   // materialized and included on top of the native context. Changes to
88   // the materialized object are written back afterwards.
89   // Note that the native context is taken from the original context chain,
90   // which may not be the current native context of the isolate.
91   ContextBuilder context_builder(isolate, frame, inlined_jsframe_index);
92   if (isolate->has_pending_exception()) return MaybeHandle<Object>();
93 
94   Handle<Context> context = context_builder.evaluation_context();
95   Handle<JSObject> receiver(context->global_proxy(), isolate);
96   MaybeHandle<Object> maybe_result =
97       Evaluate(isolate, context_builder.outer_info(), context, receiver, source,
98                throw_on_side_effect);
99   if (!maybe_result.is_null()) context_builder.UpdateValues();
100   return maybe_result;
101 }
102 
WebAssembly(Handle<WasmInstanceObject> instance,StackFrameId frame_id,Handle<String> source,bool throw_on_side_effect)103 V8_EXPORT MaybeHandle<Object> DebugEvaluate::WebAssembly(
104     Handle<WasmInstanceObject> instance, StackFrameId frame_id,
105     Handle<String> source, bool throw_on_side_effect) {
106   Isolate* isolate = instance->GetIsolate();
107 
108   StackTraceFrameIterator it(isolate, frame_id);
109   if (!it.is_wasm()) return isolate->factory()->undefined_value();
110   WasmFrame* frame = WasmFrame::cast(it.frame());
111 
112   Handle<JSProxy> context_extension = WasmJs::GetJSDebugProxy(frame);
113 
114   DisableBreak disable_break_scope(isolate->debug(), /*disable=*/true);
115 
116   Handle<SharedFunctionInfo> shared_info;
117   if (!GetFunctionInfo(isolate, source, REPLMode::kNo).ToHandle(&shared_info)) {
118     return {};
119   }
120 
121   Handle<ScopeInfo> scope_info =
122       ScopeInfo::CreateForWithScope(isolate, Handle<ScopeInfo>::null());
123   Handle<Context> context = isolate->factory()->NewWithContext(
124       isolate->native_context(), scope_info, context_extension);
125 
126   Handle<Object> result;
127   if (!DebugEvaluate::Evaluate(isolate, shared_info, context, context_extension,
128                                source, throw_on_side_effect)
129            .ToHandle(&result)) {
130     return {};
131   }
132 
133   return result;
134 }
135 
WithTopmostArguments(Isolate * isolate,Handle<String> source)136 MaybeHandle<Object> DebugEvaluate::WithTopmostArguments(Isolate* isolate,
137                                                         Handle<String> source) {
138   // Handle the processing of break.
139   DisableBreak disable_break_scope(isolate->debug());
140   Factory* factory = isolate->factory();
141   JavaScriptFrameIterator it(isolate);
142 
143   // Get context and receiver.
144   Handle<Context> native_context(
145       Context::cast(it.frame()->context()).native_context(), isolate);
146 
147   // Materialize arguments as property on an extension object.
148   Handle<JSObject> materialized = factory->NewJSObjectWithNullProto();
149   Handle<String> arguments_str = factory->arguments_string();
150   JSObject::SetOwnPropertyIgnoreAttributes(
151       materialized, arguments_str,
152       Accessors::FunctionGetArguments(it.frame(), 0), NONE)
153       .Check();
154 
155   // Materialize receiver.
156   Handle<Object> this_value(it.frame()->receiver(), isolate);
157   DCHECK_EQ(it.frame()->IsConstructor(), this_value->IsTheHole(isolate));
158   if (!this_value->IsTheHole(isolate)) {
159     Handle<String> this_str = factory->this_string();
160     JSObject::SetOwnPropertyIgnoreAttributes(materialized, this_str, this_value,
161                                              NONE)
162         .Check();
163   }
164 
165   // Use extension object in a debug-evaluate scope.
166   Handle<ScopeInfo> scope_info =
167       ScopeInfo::CreateForWithScope(isolate, Handle<ScopeInfo>::null());
168   scope_info->SetIsDebugEvaluateScope();
169   Handle<Context> evaluation_context =
170       factory->NewDebugEvaluateContext(native_context, scope_info, materialized,
171                                        Handle<Context>(), Handle<StringSet>());
172   Handle<SharedFunctionInfo> outer_info(
173       native_context->empty_function().shared(), isolate);
174   Handle<JSObject> receiver(native_context->global_proxy(), isolate);
175   const bool throw_on_side_effect = false;
176   MaybeHandle<Object> maybe_result =
177       Evaluate(isolate, outer_info, evaluation_context, receiver, source,
178                throw_on_side_effect);
179   return maybe_result;
180 }
181 
182 // 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)183 MaybeHandle<Object> DebugEvaluate::Evaluate(
184     Isolate* isolate, Handle<SharedFunctionInfo> outer_info,
185     Handle<Context> context, Handle<Object> receiver, Handle<String> source,
186     bool throw_on_side_effect) {
187   Handle<JSFunction> eval_fun;
188   ASSIGN_RETURN_ON_EXCEPTION(
189       isolate, eval_fun,
190       Compiler::GetFunctionFromEval(source, outer_info, context,
191                                     LanguageMode::kSloppy, NO_PARSE_RESTRICTION,
192                                     kNoSourcePosition, kNoSourcePosition,
193                                     kNoSourcePosition),
194       Object);
195 
196   Handle<Object> result;
197   bool success = false;
198   if (throw_on_side_effect) isolate->debug()->StartSideEffectCheckMode();
199   success = Execution::Call(isolate, eval_fun, receiver, 0, nullptr)
200                 .ToHandle(&result);
201   if (throw_on_side_effect) isolate->debug()->StopSideEffectCheckMode();
202   if (!success) DCHECK(isolate->has_pending_exception());
203   return success ? result : MaybeHandle<Object>();
204 }
205 
outer_info() const206 Handle<SharedFunctionInfo> DebugEvaluate::ContextBuilder::outer_info() const {
207   return handle(frame_inspector_.GetFunction()->shared(), isolate_);
208 }
209 
ContextBuilder(Isolate * isolate,JavaScriptFrame * frame,int inlined_jsframe_index)210 DebugEvaluate::ContextBuilder::ContextBuilder(Isolate* isolate,
211                                               JavaScriptFrame* frame,
212                                               int inlined_jsframe_index)
213     : isolate_(isolate),
214       frame_inspector_(frame, inlined_jsframe_index, isolate),
215       scope_iterator_(isolate, &frame_inspector_,
216                       ScopeIterator::ReparseStrategy::kScript) {
217   Handle<Context> outer_context(frame_inspector_.GetFunction()->context(),
218                                 isolate);
219   evaluation_context_ = outer_context;
220   Factory* factory = isolate->factory();
221 
222   if (scope_iterator_.Done()) return;
223 
224   // To evaluate as if we were running eval at the point of the debug break,
225   // we reconstruct the context chain as follows:
226   //  - To make stack-allocated variables visible, we materialize them and
227   //    use a debug-evaluate context to wrap both the materialized object and
228   //    the original context.
229   //  - We also wrap all contexts on the chain between the original context
230   //    and the function context.
231   //  - Between the function scope and the native context, we only resolve
232   //    variable names that are guaranteed to not be shadowed by stack-allocated
233   //    variables. Contexts between the function context and the original
234   //    context have a blocklist attached to implement that.
235   // Context::Lookup has special handling for debug-evaluate contexts:
236   //  - Look up in the materialized stack variables.
237   //  - Check the blocklist to find out whether to abort further lookup.
238   //  - Look up in the original context.
239   for (; !scope_iterator_.Done(); scope_iterator_.Next()) {
240     ScopeIterator::ScopeType scope_type = scope_iterator_.Type();
241     if (scope_type == ScopeIterator::ScopeTypeScript) break;
242     ContextChainElement context_chain_element;
243     if (scope_iterator_.InInnerScope() &&
244         (scope_type == ScopeIterator::ScopeTypeLocal ||
245          scope_iterator_.DeclaresLocals(ScopeIterator::Mode::STACK))) {
246       context_chain_element.materialized_object =
247           scope_iterator_.ScopeObject(ScopeIterator::Mode::STACK);
248     }
249     if (scope_iterator_.HasContext()) {
250       context_chain_element.wrapped_context = scope_iterator_.CurrentContext();
251     }
252     if (!scope_iterator_.InInnerScope()) {
253       context_chain_element.blocklist = scope_iterator_.GetLocals();
254     }
255     context_chain_.push_back(context_chain_element);
256   }
257 
258   Handle<ScopeInfo> scope_info =
259       evaluation_context_->IsNativeContext()
260           ? Handle<ScopeInfo>::null()
261           : handle(evaluation_context_->scope_info(), isolate);
262   for (auto rit = context_chain_.rbegin(); rit != context_chain_.rend();
263        rit++) {
264     ContextChainElement element = *rit;
265     scope_info = ScopeInfo::CreateForWithScope(isolate, scope_info);
266     scope_info->SetIsDebugEvaluateScope();
267     evaluation_context_ = factory->NewDebugEvaluateContext(
268         evaluation_context_, scope_info, element.materialized_object,
269         element.wrapped_context, element.blocklist);
270   }
271 }
272 
UpdateValues()273 void DebugEvaluate::ContextBuilder::UpdateValues() {
274   scope_iterator_.Restart();
275   for (ContextChainElement& element : context_chain_) {
276     if (!element.materialized_object.is_null()) {
277       Handle<FixedArray> keys =
278           KeyAccumulator::GetKeys(element.materialized_object,
279                                   KeyCollectionMode::kOwnOnly,
280                                   ENUMERABLE_STRINGS)
281               .ToHandleChecked();
282 
283       for (int i = 0; i < keys->length(); i++) {
284         DCHECK(keys->get(i).IsString());
285         Handle<String> key(String::cast(keys->get(i)), isolate_);
286         Handle<Object> value =
287             JSReceiver::GetDataProperty(element.materialized_object, key);
288         scope_iterator_.SetVariableValue(key, value);
289       }
290     }
291     scope_iterator_.Next();
292   }
293 }
294 
295 namespace {
296 
IntrinsicHasNoSideEffect(Runtime::FunctionId id)297 bool IntrinsicHasNoSideEffect(Runtime::FunctionId id) {
298 // Use macro to include only the non-inlined version of an intrinsic.
299 #define INTRINSIC_ALLOWLIST(V)                \
300   /* Conversions */                           \
301   V(NumberToStringSlow)                       \
302   V(ToBigInt)                                 \
303   V(ToLength)                                 \
304   V(ToNumber)                                 \
305   V(ToObject)                                 \
306   V(ToString)                                 \
307   /* Type checks */                           \
308   V(IsArray)                                  \
309   V(IsFunction)                               \
310   V(IsJSProxy)                                \
311   V(IsJSReceiver)                             \
312   V(IsRegExp)                                 \
313   V(IsSmi)                                    \
314   /* Loads */                                 \
315   V(LoadLookupSlotForCall)                    \
316   V(GetProperty)                              \
317   /* Arrays */                                \
318   V(ArraySpeciesConstructor)                  \
319   V(HasFastPackedElements)                    \
320   V(NewArray)                                 \
321   V(NormalizeElements)                        \
322   V(TypedArrayGetBuffer)                      \
323   /* Errors */                                \
324   V(NewTypeError)                             \
325   V(ReThrow)                                  \
326   V(ThrowCalledNonCallable)                   \
327   V(ThrowInvalidStringLength)                 \
328   V(ThrowIteratorError)                       \
329   V(ThrowIteratorResultNotAnObject)           \
330   V(ThrowPatternAssignmentNonCoercible)       \
331   V(ThrowReferenceError)                      \
332   V(ThrowSymbolIteratorInvalid)               \
333   /* Strings */                               \
334   V(StringIncludes)                           \
335   V(StringIndexOf)                            \
336   V(StringReplaceOneCharWithString)           \
337   V(StringSubstring)                          \
338   V(StringToNumber)                           \
339   V(StringTrim)                               \
340   /* BigInts */                               \
341   V(BigIntEqualToBigInt)                      \
342   V(BigIntToBoolean)                          \
343   V(BigIntToNumber)                           \
344   /* Literals */                              \
345   V(CreateArrayLiteral)                       \
346   V(CreateArrayLiteralWithoutAllocationSite)  \
347   V(CreateObjectLiteral)                      \
348   V(CreateObjectLiteralWithoutAllocationSite) \
349   V(CreateRegExpLiteral)                      \
350   /* Called from builtins */                  \
351   V(AllocateInYoungGeneration)                \
352   V(AllocateInOldGeneration)                  \
353   V(AllocateSeqOneByteString)                 \
354   V(AllocateSeqTwoByteString)                 \
355   V(ArrayIncludes_Slow)                       \
356   V(ArrayIndexOf)                             \
357   V(ArrayIsArray)                             \
358   V(GetFunctionName)                          \
359   V(GetOwnPropertyDescriptor)                 \
360   V(GlobalPrint)                              \
361   V(HasProperty)                              \
362   V(ObjectCreate)                             \
363   V(ObjectEntries)                            \
364   V(ObjectEntriesSkipFastPath)                \
365   V(ObjectHasOwnProperty)                     \
366   V(ObjectKeys)                               \
367   V(ObjectValues)                             \
368   V(ObjectValuesSkipFastPath)                 \
369   V(ObjectGetOwnPropertyNames)                \
370   V(ObjectGetOwnPropertyNamesTryFast)         \
371   V(ObjectIsExtensible)                       \
372   V(RegExpInitializeAndCompile)               \
373   V(StackGuard)                               \
374   V(StringAdd)                                \
375   V(StringCharCodeAt)                         \
376   V(StringEqual)                              \
377   V(StringIndexOfUnchecked)                   \
378   V(StringParseFloat)                         \
379   V(StringParseInt)                           \
380   V(SymbolDescriptiveString)                  \
381   V(ThrowRangeError)                          \
382   V(ThrowTypeError)                           \
383   V(ToName)                                   \
384   V(TransitionElementsKind)                   \
385   /* Misc. */                                 \
386   V(Call)                                     \
387   V(CompleteInobjectSlackTrackingForMap)      \
388   V(HasInPrototypeChain)                      \
389   V(IncrementUseCounter)                      \
390   V(MaxSmi)                                   \
391   V(NewObject)                                \
392   V(StringMaxLength)                          \
393   V(StringToArray)                            \
394   V(AsyncFunctionEnter)                       \
395   V(AsyncFunctionReject)                      \
396   V(AsyncFunctionResolve)                     \
397   /* Test */                                  \
398   V(GetOptimizationStatus)                    \
399   V(OptimizeFunctionOnNextCall)               \
400   V(OptimizeOsr)                              \
401   V(UnblockConcurrentRecompilation)
402 
403 // Intrinsics with inline versions have to be allowlisted here a second time.
404 #define INLINE_INTRINSIC_ALLOWLIST(V) \
405   V(Call)                             \
406   V(IsJSReceiver)                     \
407   V(AsyncFunctionEnter)               \
408   V(AsyncFunctionReject)              \
409   V(AsyncFunctionResolve)
410 
411 #define CASE(Name) case Runtime::k##Name:
412 #define INLINE_CASE(Name) case Runtime::kInline##Name:
413   switch (id) {
414     INTRINSIC_ALLOWLIST(CASE)
415     INLINE_INTRINSIC_ALLOWLIST(INLINE_CASE)
416     return true;
417     default:
418       if (FLAG_trace_side_effect_free_debug_evaluate) {
419         PrintF("[debug-evaluate] intrinsic %s may cause side effect.\n",
420                Runtime::FunctionForId(id)->name);
421       }
422       return false;
423   }
424 
425 #undef CASE
426 #undef INLINE_CASE
427 #undef INTRINSIC_ALLOWLIST
428 #undef INLINE_INTRINSIC_ALLOWLIST
429 }
430 
BytecodeHasNoSideEffect(interpreter::Bytecode bytecode)431 bool BytecodeHasNoSideEffect(interpreter::Bytecode bytecode) {
432   using interpreter::Bytecode;
433   using interpreter::Bytecodes;
434   if (Bytecodes::IsWithoutExternalSideEffects(bytecode)) return true;
435   if (Bytecodes::IsCallOrConstruct(bytecode)) return true;
436   if (Bytecodes::IsJumpIfToBoolean(bytecode)) return true;
437   if (Bytecodes::IsPrefixScalingBytecode(bytecode)) return true;
438   switch (bytecode) {
439     // Allowlist for bytecodes.
440     // Loads.
441     case Bytecode::kLdaLookupSlot:
442     case Bytecode::kLdaGlobal:
443     case Bytecode::kLdaNamedProperty:
444     case Bytecode::kLdaNamedPropertyNoFeedback:
445     case Bytecode::kLdaKeyedProperty:
446     case Bytecode::kLdaGlobalInsideTypeof:
447     case Bytecode::kLdaLookupSlotInsideTypeof:
448     case Bytecode::kGetIterator:
449     // Arithmetics.
450     case Bytecode::kAdd:
451     case Bytecode::kAddSmi:
452     case Bytecode::kSub:
453     case Bytecode::kSubSmi:
454     case Bytecode::kMul:
455     case Bytecode::kMulSmi:
456     case Bytecode::kDiv:
457     case Bytecode::kDivSmi:
458     case Bytecode::kMod:
459     case Bytecode::kModSmi:
460     case Bytecode::kExp:
461     case Bytecode::kExpSmi:
462     case Bytecode::kNegate:
463     case Bytecode::kBitwiseAnd:
464     case Bytecode::kBitwiseAndSmi:
465     case Bytecode::kBitwiseNot:
466     case Bytecode::kBitwiseOr:
467     case Bytecode::kBitwiseOrSmi:
468     case Bytecode::kBitwiseXor:
469     case Bytecode::kBitwiseXorSmi:
470     case Bytecode::kShiftLeft:
471     case Bytecode::kShiftLeftSmi:
472     case Bytecode::kShiftRight:
473     case Bytecode::kShiftRightSmi:
474     case Bytecode::kShiftRightLogical:
475     case Bytecode::kShiftRightLogicalSmi:
476     case Bytecode::kInc:
477     case Bytecode::kDec:
478     case Bytecode::kLogicalNot:
479     case Bytecode::kToBooleanLogicalNot:
480     case Bytecode::kTypeOf:
481     // Contexts.
482     case Bytecode::kCreateBlockContext:
483     case Bytecode::kCreateCatchContext:
484     case Bytecode::kCreateFunctionContext:
485     case Bytecode::kCreateEvalContext:
486     case Bytecode::kCreateWithContext:
487     // Literals.
488     case Bytecode::kCreateArrayLiteral:
489     case Bytecode::kCreateEmptyArrayLiteral:
490     case Bytecode::kCreateArrayFromIterable:
491     case Bytecode::kCreateObjectLiteral:
492     case Bytecode::kCreateEmptyObjectLiteral:
493     case Bytecode::kCreateRegExpLiteral:
494     // Allocations.
495     case Bytecode::kCreateClosure:
496     case Bytecode::kCreateUnmappedArguments:
497     case Bytecode::kCreateRestParameter:
498     // Comparisons.
499     case Bytecode::kTestEqual:
500     case Bytecode::kTestEqualStrict:
501     case Bytecode::kTestLessThan:
502     case Bytecode::kTestLessThanOrEqual:
503     case Bytecode::kTestGreaterThan:
504     case Bytecode::kTestGreaterThanOrEqual:
505     case Bytecode::kTestInstanceOf:
506     case Bytecode::kTestIn:
507     case Bytecode::kTestReferenceEqual:
508     case Bytecode::kTestUndetectable:
509     case Bytecode::kTestTypeOf:
510     case Bytecode::kTestUndefined:
511     case Bytecode::kTestNull:
512     // Conversions.
513     case Bytecode::kToObject:
514     case Bytecode::kToName:
515     case Bytecode::kToNumber:
516     case Bytecode::kToNumeric:
517     case Bytecode::kToString:
518     // Misc.
519     case Bytecode::kIncBlockCounter:  // Coverage counters.
520     case Bytecode::kForInEnumerate:
521     case Bytecode::kForInPrepare:
522     case Bytecode::kForInContinue:
523     case Bytecode::kForInNext:
524     case Bytecode::kForInStep:
525     case Bytecode::kJumpLoop:
526     case Bytecode::kThrow:
527     case Bytecode::kReThrow:
528     case Bytecode::kThrowReferenceErrorIfHole:
529     case Bytecode::kThrowSuperNotCalledIfHole:
530     case Bytecode::kThrowSuperAlreadyCalledIfNotHole:
531     case Bytecode::kIllegal:
532     case Bytecode::kCallJSRuntime:
533     case Bytecode::kReturn:
534     case Bytecode::kSetPendingMessage:
535       return true;
536     default:
537       return false;
538   }
539 }
540 
BuiltinGetSideEffectState(Builtins::Name id)541 DebugInfo::SideEffectState BuiltinGetSideEffectState(Builtins::Name id) {
542   switch (id) {
543     // Allowlist for builtins.
544     // Object builtins.
545     case Builtins::kObjectConstructor:
546     case Builtins::kObjectCreate:
547     case Builtins::kObjectEntries:
548     case Builtins::kObjectGetOwnPropertyDescriptor:
549     case Builtins::kObjectGetOwnPropertyDescriptors:
550     case Builtins::kObjectGetOwnPropertyNames:
551     case Builtins::kObjectGetOwnPropertySymbols:
552     case Builtins::kObjectGetPrototypeOf:
553     case Builtins::kObjectIs:
554     case Builtins::kObjectIsExtensible:
555     case Builtins::kObjectIsFrozen:
556     case Builtins::kObjectIsSealed:
557     case Builtins::kObjectKeys:
558     case Builtins::kObjectPrototypeValueOf:
559     case Builtins::kObjectValues:
560     case Builtins::kObjectPrototypeHasOwnProperty:
561     case Builtins::kObjectPrototypeIsPrototypeOf:
562     case Builtins::kObjectPrototypePropertyIsEnumerable:
563     case Builtins::kObjectPrototypeToString:
564     case Builtins::kObjectPrototypeToLocaleString:
565     // Array builtins.
566     case Builtins::kArrayIsArray:
567     case Builtins::kArrayConstructor:
568     case Builtins::kArrayIndexOf:
569     case Builtins::kArrayPrototypeValues:
570     case Builtins::kArrayIncludes:
571     case Builtins::kArrayPrototypeEntries:
572     case Builtins::kArrayPrototypeFill:
573     case Builtins::kArrayPrototypeFind:
574     case Builtins::kArrayPrototypeFindIndex:
575     case Builtins::kArrayPrototypeFlat:
576     case Builtins::kArrayPrototypeFlatMap:
577     case Builtins::kArrayPrototypeJoin:
578     case Builtins::kArrayPrototypeKeys:
579     case Builtins::kArrayPrototypeLastIndexOf:
580     case Builtins::kArrayPrototypeSlice:
581     case Builtins::kArrayPrototypeToLocaleString:
582     case Builtins::kArrayPrototypeToString:
583     case Builtins::kArrayForEach:
584     case Builtins::kArrayEvery:
585     case Builtins::kArraySome:
586     case Builtins::kArrayConcat:
587     case Builtins::kArrayFilter:
588     case Builtins::kArrayMap:
589     case Builtins::kArrayReduce:
590     case Builtins::kArrayReduceRight:
591     // Trace builtins.
592     case Builtins::kIsTraceCategoryEnabled:
593     case Builtins::kTrace:
594     // TypedArray builtins.
595     case Builtins::kTypedArrayConstructor:
596     case Builtins::kTypedArrayPrototypeBuffer:
597     case Builtins::kTypedArrayPrototypeByteLength:
598     case Builtins::kTypedArrayPrototypeByteOffset:
599     case Builtins::kTypedArrayPrototypeLength:
600     case Builtins::kTypedArrayPrototypeEntries:
601     case Builtins::kTypedArrayPrototypeKeys:
602     case Builtins::kTypedArrayPrototypeValues:
603     case Builtins::kTypedArrayPrototypeFind:
604     case Builtins::kTypedArrayPrototypeFindIndex:
605     case Builtins::kTypedArrayPrototypeIncludes:
606     case Builtins::kTypedArrayPrototypeJoin:
607     case Builtins::kTypedArrayPrototypeIndexOf:
608     case Builtins::kTypedArrayPrototypeLastIndexOf:
609     case Builtins::kTypedArrayPrototypeSlice:
610     case Builtins::kTypedArrayPrototypeSubArray:
611     case Builtins::kTypedArrayPrototypeEvery:
612     case Builtins::kTypedArrayPrototypeSome:
613     case Builtins::kTypedArrayPrototypeToLocaleString:
614     case Builtins::kTypedArrayPrototypeFilter:
615     case Builtins::kTypedArrayPrototypeMap:
616     case Builtins::kTypedArrayPrototypeReduce:
617     case Builtins::kTypedArrayPrototypeReduceRight:
618     case Builtins::kTypedArrayPrototypeForEach:
619     // ArrayBuffer builtins.
620     case Builtins::kArrayBufferConstructor:
621     case Builtins::kArrayBufferPrototypeGetByteLength:
622     case Builtins::kArrayBufferIsView:
623     case Builtins::kArrayBufferPrototypeSlice:
624     case Builtins::kReturnReceiver:
625     // DataView builtins.
626     case Builtins::kDataViewConstructor:
627     case Builtins::kDataViewPrototypeGetBuffer:
628     case Builtins::kDataViewPrototypeGetByteLength:
629     case Builtins::kDataViewPrototypeGetByteOffset:
630     case Builtins::kDataViewPrototypeGetInt8:
631     case Builtins::kDataViewPrototypeGetUint8:
632     case Builtins::kDataViewPrototypeGetInt16:
633     case Builtins::kDataViewPrototypeGetUint16:
634     case Builtins::kDataViewPrototypeGetInt32:
635     case Builtins::kDataViewPrototypeGetUint32:
636     case Builtins::kDataViewPrototypeGetFloat32:
637     case Builtins::kDataViewPrototypeGetFloat64:
638     case Builtins::kDataViewPrototypeGetBigInt64:
639     case Builtins::kDataViewPrototypeGetBigUint64:
640     // Boolean bulitins.
641     case Builtins::kBooleanConstructor:
642     case Builtins::kBooleanPrototypeToString:
643     case Builtins::kBooleanPrototypeValueOf:
644     // Date builtins.
645     case Builtins::kDateConstructor:
646     case Builtins::kDateNow:
647     case Builtins::kDateParse:
648     case Builtins::kDatePrototypeGetDate:
649     case Builtins::kDatePrototypeGetDay:
650     case Builtins::kDatePrototypeGetFullYear:
651     case Builtins::kDatePrototypeGetHours:
652     case Builtins::kDatePrototypeGetMilliseconds:
653     case Builtins::kDatePrototypeGetMinutes:
654     case Builtins::kDatePrototypeGetMonth:
655     case Builtins::kDatePrototypeGetSeconds:
656     case Builtins::kDatePrototypeGetTime:
657     case Builtins::kDatePrototypeGetTimezoneOffset:
658     case Builtins::kDatePrototypeGetUTCDate:
659     case Builtins::kDatePrototypeGetUTCDay:
660     case Builtins::kDatePrototypeGetUTCFullYear:
661     case Builtins::kDatePrototypeGetUTCHours:
662     case Builtins::kDatePrototypeGetUTCMilliseconds:
663     case Builtins::kDatePrototypeGetUTCMinutes:
664     case Builtins::kDatePrototypeGetUTCMonth:
665     case Builtins::kDatePrototypeGetUTCSeconds:
666     case Builtins::kDatePrototypeGetYear:
667     case Builtins::kDatePrototypeToDateString:
668     case Builtins::kDatePrototypeToISOString:
669     case Builtins::kDatePrototypeToUTCString:
670     case Builtins::kDatePrototypeToString:
671 #ifdef V8_INTL_SUPPORT
672     case Builtins::kDatePrototypeToLocaleString:
673     case Builtins::kDatePrototypeToLocaleDateString:
674     case Builtins::kDatePrototypeToLocaleTimeString:
675 #endif
676     case Builtins::kDatePrototypeToTimeString:
677     case Builtins::kDatePrototypeToJson:
678     case Builtins::kDatePrototypeToPrimitive:
679     case Builtins::kDatePrototypeValueOf:
680     // Map builtins.
681     case Builtins::kMapConstructor:
682     case Builtins::kMapPrototypeForEach:
683     case Builtins::kMapPrototypeGet:
684     case Builtins::kMapPrototypeHas:
685     case Builtins::kMapPrototypeEntries:
686     case Builtins::kMapPrototypeGetSize:
687     case Builtins::kMapPrototypeKeys:
688     case Builtins::kMapPrototypeValues:
689     // WeakMap builtins.
690     case Builtins::kWeakMapConstructor:
691     case Builtins::kWeakMapGet:
692     case Builtins::kWeakMapPrototypeHas:
693     // Math builtins.
694     case Builtins::kMathAbs:
695     case Builtins::kMathAcos:
696     case Builtins::kMathAcosh:
697     case Builtins::kMathAsin:
698     case Builtins::kMathAsinh:
699     case Builtins::kMathAtan:
700     case Builtins::kMathAtanh:
701     case Builtins::kMathAtan2:
702     case Builtins::kMathCeil:
703     case Builtins::kMathCbrt:
704     case Builtins::kMathExpm1:
705     case Builtins::kMathClz32:
706     case Builtins::kMathCos:
707     case Builtins::kMathCosh:
708     case Builtins::kMathExp:
709     case Builtins::kMathFloor:
710     case Builtins::kMathFround:
711     case Builtins::kMathHypot:
712     case Builtins::kMathImul:
713     case Builtins::kMathLog:
714     case Builtins::kMathLog1p:
715     case Builtins::kMathLog2:
716     case Builtins::kMathLog10:
717     case Builtins::kMathMax:
718     case Builtins::kMathMin:
719     case Builtins::kMathPow:
720     case Builtins::kMathRound:
721     case Builtins::kMathSign:
722     case Builtins::kMathSin:
723     case Builtins::kMathSinh:
724     case Builtins::kMathSqrt:
725     case Builtins::kMathTan:
726     case Builtins::kMathTanh:
727     case Builtins::kMathTrunc:
728     // Number builtins.
729     case Builtins::kNumberConstructor:
730     case Builtins::kNumberIsFinite:
731     case Builtins::kNumberIsInteger:
732     case Builtins::kNumberIsNaN:
733     case Builtins::kNumberIsSafeInteger:
734     case Builtins::kNumberParseFloat:
735     case Builtins::kNumberParseInt:
736     case Builtins::kNumberPrototypeToExponential:
737     case Builtins::kNumberPrototypeToFixed:
738     case Builtins::kNumberPrototypeToPrecision:
739     case Builtins::kNumberPrototypeToString:
740     case Builtins::kNumberPrototypeToLocaleString:
741     case Builtins::kNumberPrototypeValueOf:
742     // BigInt builtins.
743     case Builtins::kBigIntConstructor:
744     case Builtins::kBigIntAsIntN:
745     case Builtins::kBigIntAsUintN:
746     case Builtins::kBigIntPrototypeToString:
747     case Builtins::kBigIntPrototypeValueOf:
748     // Set builtins.
749     case Builtins::kSetConstructor:
750     case Builtins::kSetPrototypeEntries:
751     case Builtins::kSetPrototypeForEach:
752     case Builtins::kSetPrototypeGetSize:
753     case Builtins::kSetPrototypeHas:
754     case Builtins::kSetPrototypeValues:
755     // WeakSet builtins.
756     case Builtins::kWeakSetConstructor:
757     case Builtins::kWeakSetPrototypeHas:
758     // String builtins. Strings are immutable.
759     case Builtins::kStringFromCharCode:
760     case Builtins::kStringFromCodePoint:
761     case Builtins::kStringConstructor:
762     case Builtins::kStringPrototypeAnchor:
763     case Builtins::kStringPrototypeBig:
764     case Builtins::kStringPrototypeBlink:
765     case Builtins::kStringPrototypeBold:
766     case Builtins::kStringPrototypeCharAt:
767     case Builtins::kStringPrototypeCharCodeAt:
768     case Builtins::kStringPrototypeCodePointAt:
769     case Builtins::kStringPrototypeConcat:
770     case Builtins::kStringPrototypeEndsWith:
771     case Builtins::kStringPrototypeFixed:
772     case Builtins::kStringPrototypeFontcolor:
773     case Builtins::kStringPrototypeFontsize:
774     case Builtins::kStringPrototypeIncludes:
775     case Builtins::kStringPrototypeIndexOf:
776     case Builtins::kStringPrototypeItalics:
777     case Builtins::kStringPrototypeLastIndexOf:
778     case Builtins::kStringPrototypeLink:
779     case Builtins::kStringPrototypeMatchAll:
780     case Builtins::kStringPrototypePadEnd:
781     case Builtins::kStringPrototypePadStart:
782     case Builtins::kStringPrototypeRepeat:
783     case Builtins::kStringPrototypeSlice:
784     case Builtins::kStringPrototypeSmall:
785     case Builtins::kStringPrototypeStartsWith:
786     case Builtins::kStringPrototypeStrike:
787     case Builtins::kStringPrototypeSub:
788     case Builtins::kStringPrototypeSubstr:
789     case Builtins::kStringPrototypeSubstring:
790     case Builtins::kStringPrototypeSup:
791     case Builtins::kStringPrototypeToString:
792 #ifndef V8_INTL_SUPPORT
793     case Builtins::kStringPrototypeToLowerCase:
794     case Builtins::kStringPrototypeToUpperCase:
795 #endif
796     case Builtins::kStringPrototypeTrim:
797     case Builtins::kStringPrototypeTrimEnd:
798     case Builtins::kStringPrototypeTrimStart:
799     case Builtins::kStringPrototypeValueOf:
800     case Builtins::kStringToNumber:
801     case Builtins::kStringSubstring:
802     // Symbol builtins.
803     case Builtins::kSymbolConstructor:
804     case Builtins::kSymbolKeyFor:
805     case Builtins::kSymbolPrototypeToString:
806     case Builtins::kSymbolPrototypeValueOf:
807     case Builtins::kSymbolPrototypeToPrimitive:
808     // JSON builtins.
809     case Builtins::kJsonParse:
810     case Builtins::kJsonStringify:
811     // Global function builtins.
812     case Builtins::kGlobalDecodeURI:
813     case Builtins::kGlobalDecodeURIComponent:
814     case Builtins::kGlobalEncodeURI:
815     case Builtins::kGlobalEncodeURIComponent:
816     case Builtins::kGlobalEscape:
817     case Builtins::kGlobalUnescape:
818     case Builtins::kGlobalIsFinite:
819     case Builtins::kGlobalIsNaN:
820     // Function builtins.
821     case Builtins::kFunctionPrototypeToString:
822     case Builtins::kFunctionPrototypeBind:
823     case Builtins::kFastFunctionPrototypeBind:
824     case Builtins::kFunctionPrototypeCall:
825     case Builtins::kFunctionPrototypeApply:
826     // Error builtins.
827     case Builtins::kErrorConstructor:
828     // RegExp builtins.
829     case Builtins::kRegExpConstructor:
830     // Internal.
831     case Builtins::kStrictPoisonPillThrower:
832     case Builtins::kAllocateInYoungGeneration:
833     case Builtins::kAllocateInOldGeneration:
834     case Builtins::kAllocateRegularInYoungGeneration:
835     case Builtins::kAllocateRegularInOldGeneration:
836       return DebugInfo::kHasNoSideEffect;
837 
838     // Set builtins.
839     case Builtins::kSetIteratorPrototypeNext:
840     case Builtins::kSetPrototypeAdd:
841     case Builtins::kSetPrototypeClear:
842     case Builtins::kSetPrototypeDelete:
843     // Array builtins.
844     case Builtins::kArrayIteratorPrototypeNext:
845     case Builtins::kArrayPrototypePop:
846     case Builtins::kArrayPrototypePush:
847     case Builtins::kArrayPrototypeReverse:
848     case Builtins::kArrayPrototypeShift:
849     case Builtins::kArrayPrototypeUnshift:
850     case Builtins::kArrayPrototypeSort:
851     case Builtins::kArrayPrototypeSplice:
852     case Builtins::kArrayUnshift:
853     // Map builtins.
854     case Builtins::kMapIteratorPrototypeNext:
855     case Builtins::kMapPrototypeClear:
856     case Builtins::kMapPrototypeDelete:
857     case Builtins::kMapPrototypeSet:
858     // RegExp builtins.
859     case Builtins::kRegExpPrototypeTest:
860     case Builtins::kRegExpPrototypeExec:
861     case Builtins::kRegExpPrototypeSplit:
862     case Builtins::kRegExpPrototypeFlagsGetter:
863     case Builtins::kRegExpPrototypeGlobalGetter:
864     case Builtins::kRegExpPrototypeIgnoreCaseGetter:
865     case Builtins::kRegExpPrototypeMatchAll:
866     case Builtins::kRegExpPrototypeMultilineGetter:
867     case Builtins::kRegExpPrototypeDotAllGetter:
868     case Builtins::kRegExpPrototypeUnicodeGetter:
869     case Builtins::kRegExpPrototypeStickyGetter:
870       return DebugInfo::kRequiresRuntimeChecks;
871     default:
872       if (FLAG_trace_side_effect_free_debug_evaluate) {
873         PrintF("[debug-evaluate] built-in %s may cause side effect.\n",
874                Builtins::name(id));
875       }
876       return DebugInfo::kHasSideEffects;
877   }
878 }
879 
BytecodeRequiresRuntimeCheck(interpreter::Bytecode bytecode)880 bool BytecodeRequiresRuntimeCheck(interpreter::Bytecode bytecode) {
881   using interpreter::Bytecode;
882   switch (bytecode) {
883     case Bytecode::kStaNamedProperty:
884     case Bytecode::kStaNamedPropertyNoFeedback:
885     case Bytecode::kStaNamedOwnProperty:
886     case Bytecode::kStaKeyedProperty:
887     case Bytecode::kStaInArrayLiteral:
888     case Bytecode::kStaDataPropertyInLiteral:
889     case Bytecode::kStaCurrentContextSlot:
890       return true;
891     default:
892       return false;
893   }
894 }
895 
896 }  // anonymous namespace
897 
898 // static
FunctionGetSideEffectState(Isolate * isolate,Handle<SharedFunctionInfo> info)899 DebugInfo::SideEffectState DebugEvaluate::FunctionGetSideEffectState(
900     Isolate* isolate, Handle<SharedFunctionInfo> info) {
901   if (FLAG_trace_side_effect_free_debug_evaluate) {
902     PrintF("[debug-evaluate] Checking function %s for side effect.\n",
903            info->DebugName().ToCString().get());
904   }
905 
906   DCHECK(info->is_compiled());
907   DCHECK(!info->needs_script_context());
908   if (info->HasBytecodeArray()) {
909     // Check bytecodes against allowlist.
910     Handle<BytecodeArray> bytecode_array(info->GetBytecodeArray(), isolate);
911     if (FLAG_trace_side_effect_free_debug_evaluate) {
912       bytecode_array->Print();
913     }
914     bool requires_runtime_checks = false;
915     for (interpreter::BytecodeArrayIterator it(bytecode_array); !it.done();
916          it.Advance()) {
917       interpreter::Bytecode bytecode = it.current_bytecode();
918 
919       if (interpreter::Bytecodes::IsCallRuntime(bytecode)) {
920         Runtime::FunctionId id =
921             (bytecode == interpreter::Bytecode::kInvokeIntrinsic)
922                 ? it.GetIntrinsicIdOperand(0)
923                 : it.GetRuntimeIdOperand(0);
924         if (IntrinsicHasNoSideEffect(id)) continue;
925         return DebugInfo::kHasSideEffects;
926       }
927 
928       if (BytecodeHasNoSideEffect(bytecode)) continue;
929       if (BytecodeRequiresRuntimeCheck(bytecode)) {
930         requires_runtime_checks = true;
931         continue;
932       }
933 
934       if (FLAG_trace_side_effect_free_debug_evaluate) {
935         PrintF("[debug-evaluate] bytecode %s may cause side effect.\n",
936                interpreter::Bytecodes::ToString(bytecode));
937       }
938 
939       // Did not match allowlist.
940       return DebugInfo::kHasSideEffects;
941     }
942     return requires_runtime_checks ? DebugInfo::kRequiresRuntimeChecks
943                                    : DebugInfo::kHasNoSideEffect;
944   } else if (info->IsApiFunction()) {
945     if (info->GetCode().is_builtin()) {
946       return info->GetCode().builtin_index() == Builtins::kHandleApiCall
947                  ? DebugInfo::kHasNoSideEffect
948                  : DebugInfo::kHasSideEffects;
949     }
950   } else {
951     // Check built-ins against allowlist.
952     int builtin_index =
953         info->HasBuiltinId() ? info->builtin_id() : Builtins::kNoBuiltinId;
954     if (!Builtins::IsBuiltinId(builtin_index))
955       return DebugInfo::kHasSideEffects;
956     DebugInfo::SideEffectState state =
957         BuiltinGetSideEffectState(static_cast<Builtins::Name>(builtin_index));
958     return state;
959   }
960 
961   return DebugInfo::kHasSideEffects;
962 }
963 
964 #ifdef DEBUG
TransitivelyCalledBuiltinHasNoSideEffect(Builtins::Name caller,Builtins::Name callee)965 static bool TransitivelyCalledBuiltinHasNoSideEffect(Builtins::Name caller,
966                                                      Builtins::Name callee) {
967   switch (callee) {
968       // Transitively called Builtins:
969     case Builtins::kAbort:
970     case Builtins::kAbortCSAAssert:
971     case Builtins::kAdaptorWithBuiltinExitFrame:
972     case Builtins::kArrayConstructorImpl:
973     case Builtins::kArrayEveryLoopContinuation:
974     case Builtins::kArrayFilterLoopContinuation:
975     case Builtins::kArrayFindIndexLoopContinuation:
976     case Builtins::kArrayFindLoopContinuation:
977     case Builtins::kArrayForEachLoopContinuation:
978     case Builtins::kArrayIncludesHoleyDoubles:
979     case Builtins::kArrayIncludesPackedDoubles:
980     case Builtins::kArrayIncludesSmiOrObject:
981     case Builtins::kArrayIndexOfHoleyDoubles:
982     case Builtins::kArrayIndexOfPackedDoubles:
983     case Builtins::kArrayIndexOfSmiOrObject:
984     case Builtins::kArrayMapLoopContinuation:
985     case Builtins::kArrayReduceLoopContinuation:
986     case Builtins::kArrayReduceRightLoopContinuation:
987     case Builtins::kArraySomeLoopContinuation:
988     case Builtins::kArrayTimSort:
989     case Builtins::kCall_ReceiverIsAny:
990     case Builtins::kCall_ReceiverIsNotNullOrUndefined:
991     case Builtins::kCall_ReceiverIsNullOrUndefined:
992     case Builtins::kCallWithArrayLike:
993     case Builtins::kCEntry_Return1_DontSaveFPRegs_ArgvOnStack_NoBuiltinExit:
994     case Builtins::kCEntry_Return1_DontSaveFPRegs_ArgvOnStack_BuiltinExit:
995     case Builtins::kCEntry_Return1_DontSaveFPRegs_ArgvInRegister_NoBuiltinExit:
996     case Builtins::kCEntry_Return1_SaveFPRegs_ArgvOnStack_NoBuiltinExit:
997     case Builtins::kCEntry_Return1_SaveFPRegs_ArgvOnStack_BuiltinExit:
998     case Builtins::kCEntry_Return2_DontSaveFPRegs_ArgvOnStack_NoBuiltinExit:
999     case Builtins::kCEntry_Return2_DontSaveFPRegs_ArgvOnStack_BuiltinExit:
1000     case Builtins::kCEntry_Return2_DontSaveFPRegs_ArgvInRegister_NoBuiltinExit:
1001     case Builtins::kCEntry_Return2_SaveFPRegs_ArgvOnStack_NoBuiltinExit:
1002     case Builtins::kCEntry_Return2_SaveFPRegs_ArgvOnStack_BuiltinExit:
1003     case Builtins::kCloneFastJSArray:
1004     case Builtins::kConstruct:
1005     case Builtins::kConvertToLocaleString:
1006     case Builtins::kCreateTypedArray:
1007     case Builtins::kDirectCEntry:
1008     case Builtins::kDoubleToI:
1009     case Builtins::kExtractFastJSArray:
1010     case Builtins::kFastNewObject:
1011     case Builtins::kFindOrderedHashMapEntry:
1012     case Builtins::kFlatMapIntoArray:
1013     case Builtins::kFlattenIntoArray:
1014     case Builtins::kGetProperty:
1015     case Builtins::kHasProperty:
1016     case Builtins::kCreateHTML:
1017     case Builtins::kNonNumberToNumber:
1018     case Builtins::kNonPrimitiveToPrimitive_Number:
1019     case Builtins::kNumberToString:
1020     case Builtins::kObjectToString:
1021     case Builtins::kOrderedHashTableHealIndex:
1022     case Builtins::kOrdinaryToPrimitive_Number:
1023     case Builtins::kOrdinaryToPrimitive_String:
1024     case Builtins::kParseInt:
1025     case Builtins::kProxyHasProperty:
1026     case Builtins::kProxyIsExtensible:
1027     case Builtins::kProxyGetPrototypeOf:
1028     case Builtins::kRecordWrite:
1029     case Builtins::kStringAdd_CheckNone:
1030     case Builtins::kStringEqual:
1031     case Builtins::kStringIndexOf:
1032     case Builtins::kStringRepeat:
1033     case Builtins::kToInteger:
1034     case Builtins::kToLength:
1035     case Builtins::kToName:
1036     case Builtins::kToObject:
1037     case Builtins::kToString:
1038     case Builtins::kWeakMapLookupHashIndex:
1039       return true;
1040     case Builtins::kJoinStackPop:
1041     case Builtins::kJoinStackPush:
1042       switch (caller) {
1043         case Builtins::kArrayPrototypeJoin:
1044         case Builtins::kArrayPrototypeToLocaleString:
1045         case Builtins::kTypedArrayPrototypeJoin:
1046         case Builtins::kTypedArrayPrototypeToLocaleString:
1047           return true;
1048         default:
1049           return false;
1050       }
1051     case Builtins::kFastCreateDataProperty:
1052       switch (caller) {
1053         case Builtins::kArrayPrototypeSlice:
1054         case Builtins::kArrayFilter:
1055           return true;
1056         default:
1057           return false;
1058       }
1059     case Builtins::kSetProperty:
1060       switch (caller) {
1061         case Builtins::kArrayPrototypeSlice:
1062         case Builtins::kTypedArrayPrototypeMap:
1063         case Builtins::kStringPrototypeMatchAll:
1064           return true;
1065         default:
1066           return false;
1067       }
1068     default:
1069       return false;
1070   }
1071 }
1072 
1073 // static
VerifyTransitiveBuiltins(Isolate * isolate)1074 void DebugEvaluate::VerifyTransitiveBuiltins(Isolate* isolate) {
1075   // TODO(yangguo): also check runtime calls.
1076   bool failed = false;
1077   bool sanity_check = false;
1078   for (int i = 0; i < Builtins::builtin_count; i++) {
1079     Builtins::Name caller = static_cast<Builtins::Name>(i);
1080     DebugInfo::SideEffectState state = BuiltinGetSideEffectState(caller);
1081     if (state != DebugInfo::kHasNoSideEffect) continue;
1082     Code code = isolate->builtins()->builtin(caller);
1083     int mode = RelocInfo::ModeMask(RelocInfo::CODE_TARGET) |
1084                RelocInfo::ModeMask(RelocInfo::RELATIVE_CODE_TARGET);
1085 
1086     for (RelocIterator it(code, mode); !it.done(); it.next()) {
1087       RelocInfo* rinfo = it.rinfo();
1088       DCHECK(RelocInfo::IsCodeTargetMode(rinfo->rmode()));
1089       Code callee_code = isolate->heap()->GcSafeFindCodeForInnerPointer(
1090           rinfo->target_address());
1091       if (!callee_code.is_builtin()) continue;
1092       Builtins::Name callee =
1093           static_cast<Builtins::Name>(callee_code.builtin_index());
1094       if (BuiltinGetSideEffectState(callee) == DebugInfo::kHasNoSideEffect) {
1095         continue;
1096       }
1097       if (TransitivelyCalledBuiltinHasNoSideEffect(caller, callee)) {
1098         sanity_check = true;
1099         continue;
1100       }
1101       PrintF("Allowlisted builtin %s calls non-allowlisted builtin %s\n",
1102              Builtins::name(caller), Builtins::name(callee));
1103       failed = true;
1104     }
1105   }
1106   CHECK(!failed);
1107 #if defined(V8_TARGET_ARCH_PPC) || defined(V8_TARGET_ARCH_PPC64) || \
1108     defined(V8_TARGET_ARCH_MIPS64)
1109   // Isolate-independent builtin calls and jumps do not emit reloc infos
1110   // on PPC. We try to avoid using PC relative code due to performance
1111   // issue with especially older hardwares.
1112   // MIPS64 doesn't have PC relative code currently.
1113   // TODO(mips): Add PC relative code to MIPS64.
1114   USE(sanity_check);
1115 #else
1116   CHECK(sanity_check);
1117 #endif
1118 }
1119 #endif  // DEBUG
1120 
1121 // static
ApplySideEffectChecks(Handle<BytecodeArray> bytecode_array)1122 void DebugEvaluate::ApplySideEffectChecks(
1123     Handle<BytecodeArray> bytecode_array) {
1124   for (interpreter::BytecodeArrayIterator it(bytecode_array); !it.done();
1125        it.Advance()) {
1126     interpreter::Bytecode bytecode = it.current_bytecode();
1127     if (BytecodeRequiresRuntimeCheck(bytecode)) it.ApplyDebugBreak();
1128   }
1129 }
1130 
1131 }  // namespace internal
1132 }  // namespace v8
1133