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