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