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