debug-evaluate.cc 44 KB
Newer Older
1 2 3 4 5 6
// Copyright 2015 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "src/debug/debug-evaluate.h"

7
#include "src/builtins/accessors.h"
8 9
#include "src/codegen/assembler-inl.h"
#include "src/codegen/compiler.h"
10
#include "src/common/globals.h"
11 12
#include "src/debug/debug-frames.h"
#include "src/debug/debug-scopes.h"
yangguo's avatar
yangguo committed
13
#include "src/debug/debug.h"
14 15
#include "src/execution/frames-inl.h"
#include "src/execution/isolate-inl.h"
16 17
#include "src/interpreter/bytecode-array-iterator.h"
#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 24 25

namespace v8 {
namespace internal {

26 27 28 29 30 31 32 33 34 35 36 37 38 39
namespace {
static MaybeHandle<SharedFunctionInfo> GetFunctionInfo(Isolate* isolate,
                                                       Handle<String> source,
                                                       REPLMode repl_mode) {
  Compiler::ScriptDetails script_details(isolate->factory()->empty_string());
  script_details.repl_mode = repl_mode;
  ScriptOriginOptions origin_options(false, true);
  return Compiler::GetSharedFunctionInfoForScript(
      isolate, source, script_details, origin_options, nullptr, nullptr,
      ScriptCompiler::kNoCompileOptions, ScriptCompiler::kNoCacheNoReason,
      NOT_NATIVES_CODE);
}
}  // namespace

40
MaybeHandle<Object> DebugEvaluate::Global(Isolate* isolate,
41
                                          Handle<String> source,
42 43
                                          debug::EvaluateGlobalMode mode,
                                          REPLMode repl_mode) {
44
  // Disable breaks in side-effect free mode.
45 46 47 48 49
  DisableBreak disable_break_scope(
      isolate->debug(),
      mode == debug::EvaluateGlobalMode::kDisableBreaks ||
          mode ==
              debug::EvaluateGlobalMode::kDisableBreaksAndThrowOnSideEffect);
50

51
  Handle<SharedFunctionInfo> shared_info;
52 53 54
  if (!GetFunctionInfo(isolate, source, repl_mode).ToHandle(&shared_info)) {
    return MaybeHandle<Object>();
  }
55

56
  Handle<Context> context = isolate->native_context();
57 58 59
  Handle<JSFunction> fun =
      isolate->factory()->NewFunctionFromSharedFunctionInfo(shared_info,
                                                            context);
60 61 62
  if (mode == debug::EvaluateGlobalMode::kDisableBreaksAndThrowOnSideEffect) {
    isolate->debug()->StartSideEffectCheckMode();
  }
63
  MaybeHandle<Object> result = Execution::Call(
64 65
      isolate, fun, Handle<JSObject>(context->global_proxy(), isolate), 0,
      nullptr);
66 67 68
  if (mode == debug::EvaluateGlobalMode::kDisableBreaksAndThrowOnSideEffect) {
    isolate->debug()->StopSideEffectCheckMode();
  }
69
  return result;
70 71 72
}

MaybeHandle<Object> DebugEvaluate::Local(Isolate* isolate,
73
                                         StackFrameId frame_id,
74
                                         int inlined_jsframe_index,
75 76
                                         Handle<String> source,
                                         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 82 83
  StackTraceFrameIterator it(isolate, frame_id);
  if (!it.is_javascript()) return isolate->factory()->undefined_value();
  JavaScriptFrame* frame = it.javascript_frame();
84

85 86 87 88
  // This is not a lot different than DebugEvaluate::Global, except that
  // variables accessible by the function we are evaluating from are
  // materialized and included on top of the native context. Changes to
  // the materialized object are written back afterwards.
89 90
  // Note that the native context is taken from the original context chain,
  // which may not be the current native context of the isolate.
91 92 93
  ContextBuilder context_builder(isolate, frame, inlined_jsframe_index);
  if (isolate->has_pending_exception()) return MaybeHandle<Object>();

94
  Handle<Context> context = context_builder.evaluation_context();
95
  Handle<JSObject> receiver(context->global_proxy(), isolate);
96 97 98
  MaybeHandle<Object> maybe_result =
      Evaluate(isolate, context_builder.outer_info(), context, receiver, source,
               throw_on_side_effect);
99
  if (!maybe_result.is_null()) context_builder.UpdateValues();
100 101 102
  return maybe_result;
}

103 104 105 106 107 108 109
V8_EXPORT MaybeHandle<Object> DebugEvaluate::WebAssembly(
    Handle<WasmInstanceObject> instance, StackFrameId frame_id,
    Handle<String> source, bool throw_on_side_effect) {
  Isolate* isolate = instance->GetIsolate();

  StackTraceFrameIterator it(isolate, frame_id);
  if (!it.is_wasm()) return isolate->factory()->undefined_value();
110 111 112
  WasmFrame* frame = WasmFrame::cast(it.frame());

  Handle<JSProxy> context_extension = WasmJs::GetJSDebugProxy(frame);
113 114 115 116 117 118 119 120

  DisableBreak disable_break_scope(isolate->debug(), /*disable=*/true);

  Handle<SharedFunctionInfo> shared_info;
  if (!GetFunctionInfo(isolate, source, REPLMode::kNo).ToHandle(&shared_info)) {
    return {};
  }

121 122 123 124
  Handle<ScopeInfo> scope_info =
      ScopeInfo::CreateForWithScope(isolate, Handle<ScopeInfo>::null());
  Handle<Context> context = isolate->factory()->NewWithContext(
      isolate->native_context(), scope_info, context_extension);
125 126

  Handle<Object> result;
127 128
  if (!DebugEvaluate::Evaluate(isolate, shared_info, context, context_extension,
                               source, throw_on_side_effect)
129 130 131 132 133 134 135
           .ToHandle(&result)) {
    return {};
  }

  return result;
}

136 137 138 139 140 141 142 143 144
MaybeHandle<Object> DebugEvaluate::WithTopmostArguments(Isolate* isolate,
                                                        Handle<String> source) {
  // Handle the processing of break.
  DisableBreak disable_break_scope(isolate->debug());
  Factory* factory = isolate->factory();
  JavaScriptFrameIterator it(isolate);

  // Get context and receiver.
  Handle<Context> native_context(
145
      Context::cast(it.frame()->context()).native_context(), isolate);
146 147 148 149 150 151 152 153 154 155

  // Materialize arguments as property on an extension object.
  Handle<JSObject> materialized = factory->NewJSObjectWithNullProto();
  Handle<String> arguments_str = factory->arguments_string();
  JSObject::SetOwnPropertyIgnoreAttributes(
      materialized, arguments_str,
      Accessors::FunctionGetArguments(it.frame(), 0), NONE)
      .Check();

  // Materialize receiver.
156 157 158 159 160 161 162 163
  Handle<Object> this_value(it.frame()->receiver(), isolate);
  DCHECK_EQ(it.frame()->IsConstructor(), this_value->IsTheHole(isolate));
  if (!this_value->IsTheHole(isolate)) {
    Handle<String> this_str = factory->this_string();
    JSObject::SetOwnPropertyIgnoreAttributes(materialized, this_str, this_value,
                                             NONE)
        .Check();
  }
164 165 166 167 168 169 170 171

  // Use extension object in a debug-evaluate scope.
  Handle<ScopeInfo> scope_info =
      ScopeInfo::CreateForWithScope(isolate, Handle<ScopeInfo>::null());
  scope_info->SetIsDebugEvaluateScope();
  Handle<Context> evaluation_context =
      factory->NewDebugEvaluateContext(native_context, scope_info, materialized,
                                       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 176 177 178 179 180
  const bool throw_on_side_effect = false;
  MaybeHandle<Object> maybe_result =
      Evaluate(isolate, outer_info, evaluation_context, receiver, source,
               throw_on_side_effect);
  return maybe_result;
}
181 182 183 184

// Compile and evaluate source for the given context.
MaybeHandle<Object> DebugEvaluate::Evaluate(
    Isolate* isolate, Handle<SharedFunctionInfo> outer_info,
185 186
    Handle<Context> context, Handle<Object> receiver, Handle<String> source,
    bool throw_on_side_effect) {
187
  Handle<JSFunction> eval_fun;
188 189
  ASSIGN_RETURN_ON_EXCEPTION(
      isolate, eval_fun,
190 191 192 193
      Compiler::GetFunctionFromEval(source, outer_info, context,
                                    LanguageMode::kSloppy, NO_PARSE_RESTRICTION,
                                    kNoSourcePosition, kNoSourcePosition,
                                    kNoSourcePosition),
194
      Object);
195 196

  Handle<Object> result;
197
  bool success = false;
198
  if (throw_on_side_effect) isolate->debug()->StartSideEffectCheckMode();
199 200
  success = Execution::Call(isolate, eval_fun, receiver, 0, nullptr)
                .ToHandle(&result);
201
  if (throw_on_side_effect) isolate->debug()->StopSideEffectCheckMode();
202 203
  if (!success) DCHECK(isolate->has_pending_exception());
  return success ? result : MaybeHandle<Object>();
204 205
}

206 207 208
Handle<SharedFunctionInfo> DebugEvaluate::ContextBuilder::outer_info() const {
  return handle(frame_inspector_.GetFunction()->shared(), isolate_);
}
209 210 211 212 213

DebugEvaluate::ContextBuilder::ContextBuilder(Isolate* isolate,
                                              JavaScriptFrame* frame,
                                              int inlined_jsframe_index)
    : isolate_(isolate),
214 215
      frame_inspector_(frame, inlined_jsframe_index, isolate),
      scope_iterator_(isolate, &frame_inspector_,
216
                      ScopeIterator::ReparseStrategy::kScript) {
217 218
  Handle<Context> outer_context(frame_inspector_.GetFunction()->context(),
                                isolate);
219 220 221
  evaluation_context_ = outer_context;
  Factory* factory = isolate->factory();

222 223
  if (scope_iterator_.Done()) return;

224 225 226 227 228
  // To evaluate as if we were running eval at the point of the debug break,
  // we reconstruct the context chain as follows:
  //  - To make stack-allocated variables visible, we materialize them and
  //    use a debug-evaluate context to wrap both the materialized object and
  //    the original context.
229 230
  //  - We also wrap all contexts on the chain between the original context
  //    and the function context.
231
  //  - Between the function scope and the native context, we only resolve
232 233
  //    variable names that are guaranteed to not be shadowed by stack-allocated
  //    variables. Contexts between the function context and the original
Dan Elphick's avatar
Dan Elphick committed
234
  //    context have a blocklist attached to implement that.
235 236
  // Context::Lookup has special handling for debug-evaluate contexts:
  //  - Look up in the materialized stack variables.
Dan Elphick's avatar
Dan Elphick committed
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 241 242
    ScopeIterator::ScopeType scope_type = scope_iterator_.Type();
    if (scope_type == ScopeIterator::ScopeTypeScript) break;
    ContextChainElement context_chain_element;
243 244 245
    if (scope_iterator_.InInnerScope() &&
        (scope_type == ScopeIterator::ScopeTypeLocal ||
         scope_iterator_.DeclaresLocals(ScopeIterator::Mode::STACK))) {
246 247 248 249 250 251
      context_chain_element.materialized_object =
          scope_iterator_.ScopeObject(ScopeIterator::Mode::STACK);
    }
    if (scope_iterator_.HasContext()) {
      context_chain_element.wrapped_context = scope_iterator_.CurrentContext();
    }
252
    if (!scope_iterator_.InInnerScope()) {
Dan Elphick's avatar
Dan Elphick committed
253
      context_chain_element.blocklist = scope_iterator_.GetLocals();
254
    }
255
    context_chain_.push_back(context_chain_element);
256
  }
257

258 259 260 261
  Handle<ScopeInfo> scope_info =
      evaluation_context_->IsNativeContext()
          ? Handle<ScopeInfo>::null()
          : handle(evaluation_context_->scope_info(), isolate);
262 263 264
  for (auto rit = context_chain_.rbegin(); rit != context_chain_.rend();
       rit++) {
    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,
Dan Elphick's avatar
Dan Elphick committed
269
        element.wrapped_context, element.blocklist);
270 271 272 273
  }
}

void DebugEvaluate::ContextBuilder::UpdateValues() {
274
  scope_iterator_.Restart();
275
  for (ContextChainElement& element : context_chain_) {
276
    if (!element.materialized_object.is_null()) {
277 278 279 280 281 282 283
      Handle<FixedArray> keys =
          KeyAccumulator::GetKeys(element.materialized_object,
                                  KeyCollectionMode::kOwnOnly,
                                  ENUMERABLE_STRINGS)
              .ToHandleChecked();

      for (int i = 0; i < keys->length(); i++) {
284
        DCHECK(keys->get(i).IsString());
285 286 287 288 289
        Handle<String> key(String::cast(keys->get(i)), isolate_);
        Handle<Object> value =
            JSReceiver::GetDataProperty(element.materialized_object, key);
        scope_iterator_.SetVariableValue(key, value);
      }
290
    }
291
    scope_iterator_.Next();
292 293 294
  }
}

295 296 297
namespace {

bool IntrinsicHasNoSideEffect(Runtime::FunctionId id) {
298
// Use macro to include only the non-inlined version of an intrinsic.
Dan Elphick's avatar
Dan Elphick committed
299
#define INTRINSIC_ALLOWLIST(V)                \
300
  /* Conversions */                           \
301
  V(NumberToStringSlow)                       \
302 303 304 305
  V(ToBigInt)                                 \
  V(ToLength)                                 \
  V(ToNumber)                                 \
  V(ToObject)                                 \
306
  V(ToString)                                 \
307 308 309
  /* Type checks */                           \
  V(IsArray)                                  \
  V(IsFunction)                               \
310
  V(IsJSProxy)                                \
311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327
  V(IsJSReceiver)                             \
  V(IsRegExp)                                 \
  V(IsSmi)                                    \
  /* Loads */                                 \
  V(LoadLookupSlotForCall)                    \
  V(GetProperty)                              \
  /* Arrays */                                \
  V(ArraySpeciesConstructor)                  \
  V(HasFastPackedElements)                    \
  V(NewArray)                                 \
  V(NormalizeElements)                        \
  V(TypedArrayGetBuffer)                      \
  /* Errors */                                \
  V(NewTypeError)                             \
  V(ReThrow)                                  \
  V(ThrowCalledNonCallable)                   \
  V(ThrowInvalidStringLength)                 \
328
  V(ThrowIteratorError)                       \
329
  V(ThrowIteratorResultNotAnObject)           \
330
  V(ThrowPatternAssignmentNonCoercible)       \
331 332 333 334 335 336 337 338 339 340 341 342 343 344 345
  V(ThrowReferenceError)                      \
  V(ThrowSymbolIteratorInvalid)               \
  /* Strings */                               \
  V(StringIncludes)                           \
  V(StringIndexOf)                            \
  V(StringReplaceOneCharWithString)           \
  V(StringSubstring)                          \
  V(StringToNumber)                           \
  V(StringTrim)                               \
  /* BigInts */                               \
  V(BigIntEqualToBigInt)                      \
  V(BigIntToBoolean)                          \
  V(BigIntToNumber)                           \
  /* Literals */                              \
  V(CreateArrayLiteral)                       \
346
  V(CreateArrayLiteralWithoutAllocationSite)  \
347 348 349 350
  V(CreateObjectLiteral)                      \
  V(CreateObjectLiteralWithoutAllocationSite) \
  V(CreateRegExpLiteral)                      \
  /* Called from builtins */                  \
351 352
  V(AllocateInYoungGeneration)                \
  V(AllocateInOldGeneration)                  \
353 354 355 356 357 358 359 360 361 362 363 364 365
  V(AllocateSeqOneByteString)                 \
  V(AllocateSeqTwoByteString)                 \
  V(ArrayIncludes_Slow)                       \
  V(ArrayIndexOf)                             \
  V(ArrayIsArray)                             \
  V(GetFunctionName)                          \
  V(GetOwnPropertyDescriptor)                 \
  V(GlobalPrint)                              \
  V(HasProperty)                              \
  V(ObjectCreate)                             \
  V(ObjectEntries)                            \
  V(ObjectEntriesSkipFastPath)                \
  V(ObjectHasOwnProperty)                     \
366
  V(ObjectKeys)                               \
367 368 369
  V(ObjectValues)                             \
  V(ObjectValuesSkipFastPath)                 \
  V(ObjectGetOwnPropertyNames)                \
370
  V(ObjectGetOwnPropertyNamesTryFast)         \
371
  V(ObjectIsExtensible)                       \
372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388
  V(RegExpInitializeAndCompile)               \
  V(StackGuard)                               \
  V(StringAdd)                                \
  V(StringCharCodeAt)                         \
  V(StringEqual)                              \
  V(StringIndexOfUnchecked)                   \
  V(StringParseFloat)                         \
  V(StringParseInt)                           \
  V(SymbolDescriptiveString)                  \
  V(ThrowRangeError)                          \
  V(ThrowTypeError)                           \
  V(ToName)                                   \
  V(TransitionElementsKind)                   \
  /* Misc. */                                 \
  V(Call)                                     \
  V(CompleteInobjectSlackTrackingForMap)      \
  V(HasInPrototypeChain)                      \
389
  V(IncrementUseCounter)                      \
390 391 392 393
  V(MaxSmi)                                   \
  V(NewObject)                                \
  V(StringMaxLength)                          \
  V(StringToArray)                            \
394 395 396
  V(AsyncFunctionEnter)                       \
  V(AsyncFunctionReject)                      \
  V(AsyncFunctionResolve)                     \
397 398 399 400
  /* Test */                                  \
  V(GetOptimizationStatus)                    \
  V(OptimizeFunctionOnNextCall)               \
  V(OptimizeOsr)                              \
401
  V(UnblockConcurrentRecompilation)
402

Dan Elphick's avatar
Dan Elphick committed
403 404
// Intrinsics with inline versions have to be allowlisted here a second time.
#define INLINE_INTRINSIC_ALLOWLIST(V) \
405
  V(Call)                             \
406 407 408 409
  V(IsJSReceiver)                     \
  V(AsyncFunctionEnter)               \
  V(AsyncFunctionReject)              \
  V(AsyncFunctionResolve)
410

411 412
#define CASE(Name) case Runtime::k##Name:
#define INLINE_CASE(Name) case Runtime::kInline##Name:
413
  switch (id) {
Dan Elphick's avatar
Dan Elphick committed
414 415
    INTRINSIC_ALLOWLIST(CASE)
    INLINE_INTRINSIC_ALLOWLIST(INLINE_CASE)
416
    return true;
417 418
    default:
      if (FLAG_trace_side_effect_free_debug_evaluate) {
419
        PrintF("[debug-evaluate] intrinsic %s may cause side effect.\n",
420 421 422 423
               Runtime::FunctionForId(id)->name);
      }
      return false;
  }
424 425

#undef CASE
426
#undef INLINE_CASE
Dan Elphick's avatar
Dan Elphick committed
427 428
#undef INTRINSIC_ALLOWLIST
#undef INLINE_INTRINSIC_ALLOWLIST
429 430 431
}

bool BytecodeHasNoSideEffect(interpreter::Bytecode bytecode) {
432 433
  using interpreter::Bytecode;
  using interpreter::Bytecodes;
434
  if (Bytecodes::IsWithoutExternalSideEffects(bytecode)) return true;
435
  if (Bytecodes::IsCallOrConstruct(bytecode)) return true;
436 437
  if (Bytecodes::IsJumpIfToBoolean(bytecode)) return true;
  if (Bytecodes::IsPrefixScalingBytecode(bytecode)) return true;
438
  switch (bytecode) {
Dan Elphick's avatar
Dan Elphick committed
439
    // Allowlist for bytecodes.
440
    // Loads.
441 442 443
    case Bytecode::kLdaLookupSlot:
    case Bytecode::kLdaGlobal:
    case Bytecode::kLdaNamedProperty:
444
    case Bytecode::kLdaNamedPropertyNoFeedback:
445
    case Bytecode::kLdaKeyedProperty:
446 447
    case Bytecode::kLdaGlobalInsideTypeof:
    case Bytecode::kLdaLookupSlotInsideTypeof:
448
    case Bytecode::kGetIterator:
449
    // Arithmetics.
450
    case Bytecode::kAdd:
451 452 453 454
    case Bytecode::kAddSmi:
    case Bytecode::kSub:
    case Bytecode::kSubSmi:
    case Bytecode::kMul:
455
    case Bytecode::kMulSmi:
456
    case Bytecode::kDiv:
457
    case Bytecode::kDivSmi:
458
    case Bytecode::kMod:
459
    case Bytecode::kModSmi:
460 461
    case Bytecode::kExp:
    case Bytecode::kExpSmi:
462
    case Bytecode::kNegate:
463 464
    case Bytecode::kBitwiseAnd:
    case Bytecode::kBitwiseAndSmi:
465
    case Bytecode::kBitwiseNot:
466 467 468
    case Bytecode::kBitwiseOr:
    case Bytecode::kBitwiseOrSmi:
    case Bytecode::kBitwiseXor:
469
    case Bytecode::kBitwiseXorSmi:
470 471 472 473 474
    case Bytecode::kShiftLeft:
    case Bytecode::kShiftLeftSmi:
    case Bytecode::kShiftRight:
    case Bytecode::kShiftRightSmi:
    case Bytecode::kShiftRightLogical:
475
    case Bytecode::kShiftRightLogicalSmi:
476 477 478 479 480 481 482
    case Bytecode::kInc:
    case Bytecode::kDec:
    case Bytecode::kLogicalNot:
    case Bytecode::kToBooleanLogicalNot:
    case Bytecode::kTypeOf:
    // Contexts.
    case Bytecode::kCreateBlockContext:
483
    case Bytecode::kCreateCatchContext:
484 485 486 487 488
    case Bytecode::kCreateFunctionContext:
    case Bytecode::kCreateEvalContext:
    case Bytecode::kCreateWithContext:
    // Literals.
    case Bytecode::kCreateArrayLiteral:
489
    case Bytecode::kCreateEmptyArrayLiteral:
490
    case Bytecode::kCreateArrayFromIterable:
491
    case Bytecode::kCreateObjectLiteral:
492
    case Bytecode::kCreateEmptyObjectLiteral:
493
    case Bytecode::kCreateRegExpLiteral:
494 495
    // Allocations.
    case Bytecode::kCreateClosure:
496
    case Bytecode::kCreateUnmappedArguments:
497
    case Bytecode::kCreateRestParameter:
498 499 500 501 502 503 504 505 506
    // Comparisons.
    case Bytecode::kTestEqual:
    case Bytecode::kTestEqualStrict:
    case Bytecode::kTestLessThan:
    case Bytecode::kTestLessThanOrEqual:
    case Bytecode::kTestGreaterThan:
    case Bytecode::kTestGreaterThanOrEqual:
    case Bytecode::kTestInstanceOf:
    case Bytecode::kTestIn:
507
    case Bytecode::kTestReferenceEqual:
508 509 510 511
    case Bytecode::kTestUndetectable:
    case Bytecode::kTestTypeOf:
    case Bytecode::kTestUndefined:
    case Bytecode::kTestNull:
512 513
    // Conversions.
    case Bytecode::kToObject:
514
    case Bytecode::kToName:
515 516
    case Bytecode::kToNumber:
    case Bytecode::kToNumeric:
517
    case Bytecode::kToString:
518
    // Misc.
519
    case Bytecode::kIncBlockCounter:  // Coverage counters.
520
    case Bytecode::kForInEnumerate:
521 522 523 524
    case Bytecode::kForInPrepare:
    case Bytecode::kForInContinue:
    case Bytecode::kForInNext:
    case Bytecode::kForInStep:
525
    case Bytecode::kJumpLoop:
526
    case Bytecode::kThrow:
527
    case Bytecode::kReThrow:
528 529 530
    case Bytecode::kThrowReferenceErrorIfHole:
    case Bytecode::kThrowSuperNotCalledIfHole:
    case Bytecode::kThrowSuperAlreadyCalledIfNotHole:
531 532 533
    case Bytecode::kIllegal:
    case Bytecode::kCallJSRuntime:
    case Bytecode::kReturn:
534 535 536 537 538 539 540
    case Bytecode::kSetPendingMessage:
      return true;
    default:
      return false;
  }
}

541
DebugInfo::SideEffectState BuiltinGetSideEffectState(Builtins::Name id) {
542
  switch (id) {
Dan Elphick's avatar
Dan Elphick committed
543
    // Allowlist for builtins.
544
    // Object builtins.
545
    case Builtins::kObjectConstructor:
546 547 548 549 550 551 552 553 554 555 556
    case Builtins::kObjectCreate:
    case Builtins::kObjectEntries:
    case Builtins::kObjectGetOwnPropertyDescriptor:
    case Builtins::kObjectGetOwnPropertyDescriptors:
    case Builtins::kObjectGetOwnPropertyNames:
    case Builtins::kObjectGetOwnPropertySymbols:
    case Builtins::kObjectGetPrototypeOf:
    case Builtins::kObjectIs:
    case Builtins::kObjectIsExtensible:
    case Builtins::kObjectIsFrozen:
    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 571
    case Builtins::kArrayIncludes:
    case Builtins::kArrayPrototypeEntries:
572
    case Builtins::kArrayPrototypeFill:
573 574
    case Builtins::kArrayPrototypeFind:
    case Builtins::kArrayPrototypeFindIndex:
575 576
    case Builtins::kArrayPrototypeFlat:
    case Builtins::kArrayPrototypeFlatMap:
577
    case Builtins::kArrayPrototypeJoin:
578
    case Builtins::kArrayPrototypeKeys:
579
    case Builtins::kArrayPrototypeLastIndexOf:
580
    case Builtins::kArrayPrototypeSlice:
581 582
    case Builtins::kArrayPrototypeToLocaleString:
    case Builtins::kArrayPrototypeToString:
583
    case Builtins::kArrayForEach:
584 585
    case Builtins::kArrayEvery:
    case Builtins::kArraySome:
586 587 588
    case Builtins::kArrayConcat:
    case Builtins::kArrayFilter:
    case Builtins::kArrayMap:
589
    case Builtins::kArrayReduce:
590
    case Builtins::kArrayReduceRight:
591 592 593
    // Trace builtins.
    case Builtins::kIsTraceCategoryEnabled:
    case Builtins::kTrace:
594 595 596 597 598 599 600 601 602 603 604 605
    // TypedArray builtins.
    case Builtins::kTypedArrayConstructor:
    case Builtins::kTypedArrayPrototypeBuffer:
    case Builtins::kTypedArrayPrototypeByteLength:
    case Builtins::kTypedArrayPrototypeByteOffset:
    case Builtins::kTypedArrayPrototypeLength:
    case Builtins::kTypedArrayPrototypeEntries:
    case Builtins::kTypedArrayPrototypeKeys:
    case Builtins::kTypedArrayPrototypeValues:
    case Builtins::kTypedArrayPrototypeFind:
    case Builtins::kTypedArrayPrototypeFindIndex:
    case Builtins::kTypedArrayPrototypeIncludes:
606
    case Builtins::kTypedArrayPrototypeJoin:
607 608 609 610 611 612
    case Builtins::kTypedArrayPrototypeIndexOf:
    case Builtins::kTypedArrayPrototypeLastIndexOf:
    case Builtins::kTypedArrayPrototypeSlice:
    case Builtins::kTypedArrayPrototypeSubArray:
    case Builtins::kTypedArrayPrototypeEvery:
    case Builtins::kTypedArrayPrototypeSome:
613
    case Builtins::kTypedArrayPrototypeToLocaleString:
614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637
    case Builtins::kTypedArrayPrototypeFilter:
    case Builtins::kTypedArrayPrototypeMap:
    case Builtins::kTypedArrayPrototypeReduce:
    case Builtins::kTypedArrayPrototypeReduceRight:
    case Builtins::kTypedArrayPrototypeForEach:
    // ArrayBuffer builtins.
    case Builtins::kArrayBufferConstructor:
    case Builtins::kArrayBufferPrototypeGetByteLength:
    case Builtins::kArrayBufferIsView:
    case Builtins::kArrayBufferPrototypeSlice:
    case Builtins::kReturnReceiver:
    // DataView builtins.
    case Builtins::kDataViewConstructor:
    case Builtins::kDataViewPrototypeGetBuffer:
    case Builtins::kDataViewPrototypeGetByteLength:
    case Builtins::kDataViewPrototypeGetByteOffset:
    case Builtins::kDataViewPrototypeGetInt8:
    case Builtins::kDataViewPrototypeGetUint8:
    case Builtins::kDataViewPrototypeGetInt16:
    case Builtins::kDataViewPrototypeGetUint16:
    case Builtins::kDataViewPrototypeGetInt32:
    case Builtins::kDataViewPrototypeGetUint32:
    case Builtins::kDataViewPrototypeGetFloat32:
    case Builtins::kDataViewPrototypeGetFloat64:
638 639
    case Builtins::kDataViewPrototypeGetBigInt64:
    case Builtins::kDataViewPrototypeGetBigUint64:
640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670
    // Boolean bulitins.
    case Builtins::kBooleanConstructor:
    case Builtins::kBooleanPrototypeToString:
    case Builtins::kBooleanPrototypeValueOf:
    // Date builtins.
    case Builtins::kDateConstructor:
    case Builtins::kDateNow:
    case Builtins::kDateParse:
    case Builtins::kDatePrototypeGetDate:
    case Builtins::kDatePrototypeGetDay:
    case Builtins::kDatePrototypeGetFullYear:
    case Builtins::kDatePrototypeGetHours:
    case Builtins::kDatePrototypeGetMilliseconds:
    case Builtins::kDatePrototypeGetMinutes:
    case Builtins::kDatePrototypeGetMonth:
    case Builtins::kDatePrototypeGetSeconds:
    case Builtins::kDatePrototypeGetTime:
    case Builtins::kDatePrototypeGetTimezoneOffset:
    case Builtins::kDatePrototypeGetUTCDate:
    case Builtins::kDatePrototypeGetUTCDay:
    case Builtins::kDatePrototypeGetUTCFullYear:
    case Builtins::kDatePrototypeGetUTCHours:
    case Builtins::kDatePrototypeGetUTCMilliseconds:
    case Builtins::kDatePrototypeGetUTCMinutes:
    case Builtins::kDatePrototypeGetUTCMonth:
    case Builtins::kDatePrototypeGetUTCSeconds:
    case Builtins::kDatePrototypeGetYear:
    case Builtins::kDatePrototypeToDateString:
    case Builtins::kDatePrototypeToISOString:
    case Builtins::kDatePrototypeToUTCString:
    case Builtins::kDatePrototypeToString:
671 672 673 674 675
#ifdef V8_INTL_SUPPORT
    case Builtins::kDatePrototypeToLocaleString:
    case Builtins::kDatePrototypeToLocaleDateString:
    case Builtins::kDatePrototypeToLocaleTimeString:
#endif
676 677 678 679
    case Builtins::kDatePrototypeToTimeString:
    case Builtins::kDatePrototypeToJson:
    case Builtins::kDatePrototypeToPrimitive:
    case Builtins::kDatePrototypeValueOf:
680 681
    // Map builtins.
    case Builtins::kMapConstructor:
682
    case Builtins::kMapPrototypeForEach:
683
    case Builtins::kMapPrototypeGet:
684
    case Builtins::kMapPrototypeHas:
685
    case Builtins::kMapPrototypeEntries:
686
    case Builtins::kMapPrototypeGetSize:
687 688
    case Builtins::kMapPrototypeKeys:
    case Builtins::kMapPrototypeValues:
689 690 691
    // WeakMap builtins.
    case Builtins::kWeakMapConstructor:
    case Builtins::kWeakMapGet:
692
    case Builtins::kWeakMapPrototypeHas:
693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721
    // Math builtins.
    case Builtins::kMathAbs:
    case Builtins::kMathAcos:
    case Builtins::kMathAcosh:
    case Builtins::kMathAsin:
    case Builtins::kMathAsinh:
    case Builtins::kMathAtan:
    case Builtins::kMathAtanh:
    case Builtins::kMathAtan2:
    case Builtins::kMathCeil:
    case Builtins::kMathCbrt:
    case Builtins::kMathExpm1:
    case Builtins::kMathClz32:
    case Builtins::kMathCos:
    case Builtins::kMathCosh:
    case Builtins::kMathExp:
    case Builtins::kMathFloor:
    case Builtins::kMathFround:
    case Builtins::kMathHypot:
    case Builtins::kMathImul:
    case Builtins::kMathLog:
    case Builtins::kMathLog1p:
    case Builtins::kMathLog2:
    case Builtins::kMathLog10:
    case Builtins::kMathMax:
    case Builtins::kMathMin:
    case Builtins::kMathPow:
    case Builtins::kMathRound:
    case Builtins::kMathSign:
722
    case Builtins::kMathSin:
723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739
    case Builtins::kMathSinh:
    case Builtins::kMathSqrt:
    case Builtins::kMathTan:
    case Builtins::kMathTanh:
    case Builtins::kMathTrunc:
    // Number builtins.
    case Builtins::kNumberConstructor:
    case Builtins::kNumberIsFinite:
    case Builtins::kNumberIsInteger:
    case Builtins::kNumberIsNaN:
    case Builtins::kNumberIsSafeInteger:
    case Builtins::kNumberParseFloat:
    case Builtins::kNumberParseInt:
    case Builtins::kNumberPrototypeToExponential:
    case Builtins::kNumberPrototypeToFixed:
    case Builtins::kNumberPrototypeToPrecision:
    case Builtins::kNumberPrototypeToString:
740
    case Builtins::kNumberPrototypeToLocaleString:
741
    case Builtins::kNumberPrototypeValueOf:
742 743 744 745 746 747
    // BigInt builtins.
    case Builtins::kBigIntConstructor:
    case Builtins::kBigIntAsIntN:
    case Builtins::kBigIntAsUintN:
    case Builtins::kBigIntPrototypeToString:
    case Builtins::kBigIntPrototypeValueOf:
748 749
    // Set builtins.
    case Builtins::kSetConstructor:
750
    case Builtins::kSetPrototypeEntries:
751
    case Builtins::kSetPrototypeForEach:
752
    case Builtins::kSetPrototypeGetSize:
753
    case Builtins::kSetPrototypeHas:
754
    case Builtins::kSetPrototypeValues:
755 756
    // WeakSet builtins.
    case Builtins::kWeakSetConstructor:
757
    case Builtins::kWeakSetPrototypeHas:
758 759 760 761
    // String builtins. Strings are immutable.
    case Builtins::kStringFromCharCode:
    case Builtins::kStringFromCodePoint:
    case Builtins::kStringConstructor:
762 763 764 765
    case Builtins::kStringPrototypeAnchor:
    case Builtins::kStringPrototypeBig:
    case Builtins::kStringPrototypeBlink:
    case Builtins::kStringPrototypeBold:
766 767
    case Builtins::kStringPrototypeCharAt:
    case Builtins::kStringPrototypeCharCodeAt:
768
    case Builtins::kStringPrototypeCodePointAt:
769
    case Builtins::kStringPrototypeConcat:
770
    case Builtins::kStringPrototypeEndsWith:
771 772 773
    case Builtins::kStringPrototypeFixed:
    case Builtins::kStringPrototypeFontcolor:
    case Builtins::kStringPrototypeFontsize:
774 775
    case Builtins::kStringPrototypeIncludes:
    case Builtins::kStringPrototypeIndexOf:
776
    case Builtins::kStringPrototypeItalics:
777
    case Builtins::kStringPrototypeLastIndexOf:
778
    case Builtins::kStringPrototypeLink:
779
    case Builtins::kStringPrototypeMatchAll:
780 781
    case Builtins::kStringPrototypePadEnd:
    case Builtins::kStringPrototypePadStart:
782
    case Builtins::kStringPrototypeRepeat:
783
    case Builtins::kStringPrototypeSlice:
784
    case Builtins::kStringPrototypeSmall:
785
    case Builtins::kStringPrototypeStartsWith:
786 787
    case Builtins::kStringPrototypeStrike:
    case Builtins::kStringPrototypeSub:
788 789
    case Builtins::kStringPrototypeSubstr:
    case Builtins::kStringPrototypeSubstring:
790
    case Builtins::kStringPrototypeSup:
791
    case Builtins::kStringPrototypeToString:
792
#ifndef V8_INTL_SUPPORT
793 794
    case Builtins::kStringPrototypeToLowerCase:
    case Builtins::kStringPrototypeToUpperCase:
795
#endif
796
    case Builtins::kStringPrototypeTrim:
797 798
    case Builtins::kStringPrototypeTrimEnd:
    case Builtins::kStringPrototypeTrimStart:
799
    case Builtins::kStringPrototypeValueOf:
800
    case Builtins::kStringToNumber:
801
    case Builtins::kStringSubstring:
802 803 804 805 806 807
    // Symbol builtins.
    case Builtins::kSymbolConstructor:
    case Builtins::kSymbolKeyFor:
    case Builtins::kSymbolPrototypeToString:
    case Builtins::kSymbolPrototypeValueOf:
    case Builtins::kSymbolPrototypeToPrimitive:
808 809 810
    // JSON builtins.
    case Builtins::kJsonParse:
    case Builtins::kJsonStringify:
811 812 813 814 815 816 817
    // Global function builtins.
    case Builtins::kGlobalDecodeURI:
    case Builtins::kGlobalDecodeURIComponent:
    case Builtins::kGlobalEncodeURI:
    case Builtins::kGlobalEncodeURIComponent:
    case Builtins::kGlobalEscape:
    case Builtins::kGlobalUnescape:
818 819
    case Builtins::kGlobalIsFinite:
    case Builtins::kGlobalIsNaN:
820 821 822 823 824 825
    // Function builtins.
    case Builtins::kFunctionPrototypeToString:
    case Builtins::kFunctionPrototypeBind:
    case Builtins::kFastFunctionPrototypeBind:
    case Builtins::kFunctionPrototypeCall:
    case Builtins::kFunctionPrototypeApply:
826
    // Error builtins.
827
    case Builtins::kErrorConstructor:
828 829
    // RegExp builtins.
    case Builtins::kRegExpConstructor:
830 831
    // Internal.
    case Builtins::kStrictPoisonPillThrower:
832 833
    case Builtins::kAllocateInYoungGeneration:
    case Builtins::kAllocateInOldGeneration:
834 835
    case Builtins::kAllocateRegularInYoungGeneration:
    case Builtins::kAllocateRegularInOldGeneration:
836
      return DebugInfo::kHasNoSideEffect;
837

838 839
    // Set builtins.
    case Builtins::kSetIteratorPrototypeNext:
840
    case Builtins::kSetPrototypeAdd:
841 842 843
    case Builtins::kSetPrototypeClear:
    case Builtins::kSetPrototypeDelete:
    // Array builtins.
844
    case Builtins::kArrayIteratorPrototypeNext:
845 846
    case Builtins::kArrayPrototypePop:
    case Builtins::kArrayPrototypePush:
847
    case Builtins::kArrayPrototypeReverse:
848
    case Builtins::kArrayPrototypeShift:
849
    case Builtins::kArrayPrototypeUnshift:
850
    case Builtins::kArrayPrototypeSort:
851
    case Builtins::kArrayPrototypeSplice:
852 853 854 855 856 857 858 859 860 861 862 863 864
    case Builtins::kArrayUnshift:
    // Map builtins.
    case Builtins::kMapIteratorPrototypeNext:
    case Builtins::kMapPrototypeClear:
    case Builtins::kMapPrototypeDelete:
    case Builtins::kMapPrototypeSet:
    // RegExp builtins.
    case Builtins::kRegExpPrototypeTest:
    case Builtins::kRegExpPrototypeExec:
    case Builtins::kRegExpPrototypeSplit:
    case Builtins::kRegExpPrototypeFlagsGetter:
    case Builtins::kRegExpPrototypeGlobalGetter:
    case Builtins::kRegExpPrototypeIgnoreCaseGetter:
865
    case Builtins::kRegExpPrototypeMatchAll:
866 867 868 869
    case Builtins::kRegExpPrototypeMultilineGetter:
    case Builtins::kRegExpPrototypeDotAllGetter:
    case Builtins::kRegExpPrototypeUnicodeGetter:
    case Builtins::kRegExpPrototypeStickyGetter:
870
      return DebugInfo::kRequiresRuntimeChecks;
871 872 873 874 875
    default:
      if (FLAG_trace_side_effect_free_debug_evaluate) {
        PrintF("[debug-evaluate] built-in %s may cause side effect.\n",
               Builtins::name(id));
      }
876
      return DebugInfo::kHasSideEffects;
877 878 879
  }
}

880
bool BytecodeRequiresRuntimeCheck(interpreter::Bytecode bytecode) {
881
  using interpreter::Bytecode;
882 883
  switch (bytecode) {
    case Bytecode::kStaNamedProperty:
884
    case Bytecode::kStaNamedPropertyNoFeedback:
885 886 887 888
    case Bytecode::kStaNamedOwnProperty:
    case Bytecode::kStaKeyedProperty:
    case Bytecode::kStaInArrayLiteral:
    case Bytecode::kStaDataPropertyInLiteral:
889
    case Bytecode::kStaCurrentContextSlot:
890 891 892 893 894 895
      return true;
    default:
      return false;
  }
}

896 897 898
}  // anonymous namespace

// static
899
DebugInfo::SideEffectState DebugEvaluate::FunctionGetSideEffectState(
900
    Isolate* isolate, Handle<SharedFunctionInfo> info) {
901 902
  if (FLAG_trace_side_effect_free_debug_evaluate) {
    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()) {
Dan Elphick's avatar
Dan Elphick committed
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 916 917 918 919
    for (interpreter::BytecodeArrayIterator it(bytecode_array); !it.done();
         it.Advance()) {
      interpreter::Bytecode bytecode = it.current_bytecode();

      if (interpreter::Bytecodes::IsCallRuntime(bytecode)) {
920 921 922 923 924
        Runtime::FunctionId id =
            (bytecode == interpreter::Bytecode::kInvokeIntrinsic)
                ? it.GetIntrinsicIdOperand(0)
                : it.GetRuntimeIdOperand(0);
        if (IntrinsicHasNoSideEffect(id)) continue;
925
        return DebugInfo::kHasSideEffects;
926 927 928
      }

      if (BytecodeHasNoSideEffect(bytecode)) continue;
929 930 931 932 933 934 935 936 937
      if (BytecodeRequiresRuntimeCheck(bytecode)) {
        requires_runtime_checks = true;
        continue;
      }

      if (FLAG_trace_side_effect_free_debug_evaluate) {
        PrintF("[debug-evaluate] bytecode %s may cause side effect.\n",
               interpreter::Bytecodes::ToString(bytecode));
      }
938

Dan Elphick's avatar
Dan Elphick committed
939
      // Did not match allowlist.
940
      return DebugInfo::kHasSideEffects;
941
    }
942 943
    return requires_runtime_checks ? DebugInfo::kRequiresRuntimeChecks
                                   : DebugInfo::kHasNoSideEffect;
944
  } else if (info->IsApiFunction()) {
945 946
    if (info->GetCode().is_builtin()) {
      return info->GetCode().builtin_index() == Builtins::kHandleApiCall
947 948
                 ? DebugInfo::kHasNoSideEffect
                 : DebugInfo::kHasSideEffects;
949
    }
950
  } else {
Dan Elphick's avatar
Dan Elphick committed
951
    // Check built-ins against allowlist.
952 953
    int builtin_index =
        info->HasBuiltinId() ? info->builtin_id() : Builtins::kNoBuiltinId;
954
    if (!Builtins::IsBuiltinId(builtin_index))
955 956
      return DebugInfo::kHasSideEffects;
    DebugInfo::SideEffectState state =
957 958
        BuiltinGetSideEffectState(static_cast<Builtins::Name>(builtin_index));
    return state;
959 960
  }

961
  return DebugInfo::kHasSideEffects;
962 963
}

964 965 966 967 968 969
#ifdef DEBUG
static bool TransitivelyCalledBuiltinHasNoSideEffect(Builtins::Name caller,
                                                     Builtins::Name callee) {
  switch (callee) {
      // Transitively called Builtins:
    case Builtins::kAbort:
970
    case Builtins::kAbortCSAAssert:
971 972 973 974 975 976
    case Builtins::kAdaptorWithBuiltinExitFrame:
    case Builtins::kArrayConstructorImpl:
    case Builtins::kArrayEveryLoopContinuation:
    case Builtins::kArrayFilterLoopContinuation:
    case Builtins::kArrayFindIndexLoopContinuation:
    case Builtins::kArrayFindLoopContinuation:
977
    case Builtins::kArrayForEachLoopContinuation:
978 979 980 981 982 983 984 985 986 987 988 989
    case Builtins::kArrayIncludesHoleyDoubles:
    case Builtins::kArrayIncludesPackedDoubles:
    case Builtins::kArrayIncludesSmiOrObject:
    case Builtins::kArrayIndexOfHoleyDoubles:
    case Builtins::kArrayIndexOfPackedDoubles:
    case Builtins::kArrayIndexOfSmiOrObject:
    case Builtins::kArrayMapLoopContinuation:
    case Builtins::kArrayReduceLoopContinuation:
    case Builtins::kArrayReduceRightLoopContinuation:
    case Builtins::kArraySomeLoopContinuation:
    case Builtins::kArrayTimSort:
    case Builtins::kCall_ReceiverIsAny:
990
    case Builtins::kCall_ReceiverIsNotNullOrUndefined:
991
    case Builtins::kCall_ReceiverIsNullOrUndefined:
992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015
    case Builtins::kCallWithArrayLike:
    case Builtins::kCEntry_Return1_DontSaveFPRegs_ArgvOnStack_NoBuiltinExit:
    case Builtins::kCEntry_Return1_DontSaveFPRegs_ArgvOnStack_BuiltinExit:
    case Builtins::kCEntry_Return1_DontSaveFPRegs_ArgvInRegister_NoBuiltinExit:
    case Builtins::kCEntry_Return1_SaveFPRegs_ArgvOnStack_NoBuiltinExit:
    case Builtins::kCEntry_Return1_SaveFPRegs_ArgvOnStack_BuiltinExit:
    case Builtins::kCEntry_Return2_DontSaveFPRegs_ArgvOnStack_NoBuiltinExit:
    case Builtins::kCEntry_Return2_DontSaveFPRegs_ArgvOnStack_BuiltinExit:
    case Builtins::kCEntry_Return2_DontSaveFPRegs_ArgvInRegister_NoBuiltinExit:
    case Builtins::kCEntry_Return2_SaveFPRegs_ArgvOnStack_NoBuiltinExit:
    case Builtins::kCEntry_Return2_SaveFPRegs_ArgvOnStack_BuiltinExit:
    case Builtins::kCloneFastJSArray:
    case Builtins::kConstruct:
    case Builtins::kConvertToLocaleString:
    case Builtins::kCreateTypedArray:
    case Builtins::kDirectCEntry:
    case Builtins::kDoubleToI:
    case Builtins::kExtractFastJSArray:
    case Builtins::kFastNewObject:
    case Builtins::kFindOrderedHashMapEntry:
    case Builtins::kFlatMapIntoArray:
    case Builtins::kFlattenIntoArray:
    case Builtins::kGetProperty:
    case Builtins::kHasProperty:
1016
    case Builtins::kCreateHTML:
1017 1018 1019 1020 1021 1022 1023 1024 1025
    case Builtins::kNonNumberToNumber:
    case Builtins::kNonPrimitiveToPrimitive_Number:
    case Builtins::kNumberToString:
    case Builtins::kObjectToString:
    case Builtins::kOrderedHashTableHealIndex:
    case Builtins::kOrdinaryToPrimitive_Number:
    case Builtins::kOrdinaryToPrimitive_String:
    case Builtins::kParseInt:
    case Builtins::kProxyHasProperty:
1026
    case Builtins::kProxyIsExtensible:
1027
    case Builtins::kProxyGetPrototypeOf:
1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044
    case Builtins::kRecordWrite:
    case Builtins::kStringAdd_CheckNone:
    case Builtins::kStringEqual:
    case Builtins::kStringIndexOf:
    case Builtins::kStringRepeat:
    case Builtins::kToInteger:
    case Builtins::kToLength:
    case Builtins::kToName:
    case Builtins::kToObject:
    case Builtins::kToString:
    case Builtins::kWeakMapLookupHashIndex:
      return true;
    case Builtins::kJoinStackPop:
    case Builtins::kJoinStackPush:
      switch (caller) {
        case Builtins::kArrayPrototypeJoin:
        case Builtins::kArrayPrototypeToLocaleString:
1045 1046
        case Builtins::kTypedArrayPrototypeJoin:
        case Builtins::kTypedArrayPrototypeToLocaleString:
1047 1048 1049 1050
          return true;
        default:
          return false;
      }
1051 1052 1053 1054 1055 1056 1057 1058
    case Builtins::kFastCreateDataProperty:
      switch (caller) {
        case Builtins::kArrayPrototypeSlice:
        case Builtins::kArrayFilter:
          return true;
        default:
          return false;
      }
1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090
    case Builtins::kSetProperty:
      switch (caller) {
        case Builtins::kArrayPrototypeSlice:
        case Builtins::kTypedArrayPrototypeMap:
        case Builtins::kStringPrototypeMatchAll:
          return true;
        default:
          return false;
      }
    default:
      return false;
  }
}

// static
void DebugEvaluate::VerifyTransitiveBuiltins(Isolate* isolate) {
  // TODO(yangguo): also check runtime calls.
  bool failed = false;
  bool sanity_check = false;
  for (int i = 0; i < Builtins::builtin_count; i++) {
    Builtins::Name caller = static_cast<Builtins::Name>(i);
    DebugInfo::SideEffectState state = BuiltinGetSideEffectState(caller);
    if (state != DebugInfo::kHasNoSideEffect) continue;
    Code code = isolate->builtins()->builtin(caller);
    int mode = RelocInfo::ModeMask(RelocInfo::CODE_TARGET) |
               RelocInfo::ModeMask(RelocInfo::RELATIVE_CODE_TARGET);

    for (RelocIterator it(code, mode); !it.done(); it.next()) {
      RelocInfo* rinfo = it.rinfo();
      DCHECK(RelocInfo::IsCodeTargetMode(rinfo->rmode()));
      Code callee_code = isolate->heap()->GcSafeFindCodeForInnerPointer(
          rinfo->target_address());
1091
      if (!callee_code.is_builtin()) continue;
1092
      Builtins::Name callee =
1093
          static_cast<Builtins::Name>(callee_code.builtin_index());
1094 1095 1096 1097 1098 1099 1100
      if (BuiltinGetSideEffectState(callee) == DebugInfo::kHasNoSideEffect) {
        continue;
      }
      if (TransitivelyCalledBuiltinHasNoSideEffect(caller, callee)) {
        sanity_check = true;
        continue;
      }
Dan Elphick's avatar
Dan Elphick committed
1101
      PrintF("Allowlisted builtin %s calls non-allowlisted builtin %s\n",
1102 1103 1104 1105 1106
             Builtins::name(caller), Builtins::name(callee));
      failed = true;
    }
  }
  CHECK(!failed);
1107 1108
#if defined(V8_TARGET_ARCH_PPC) || defined(V8_TARGET_ARCH_PPC64) || \
    defined(V8_TARGET_ARCH_MIPS64)
1109 1110 1111
  // Isolate-independent builtin calls and jumps do not emit reloc infos
  // on PPC. We try to avoid using PC relative code due to performance
  // issue with especially older hardwares.
1112 1113
  // MIPS64 doesn't have PC relative code currently.
  // TODO(mips): Add PC relative code to MIPS64.
1114 1115
  USE(sanity_check);
#else
1116
  CHECK(sanity_check);
1117
#endif
1118 1119 1120
}
#endif  // DEBUG

1121 1122 1123 1124 1125 1126
// static
void DebugEvaluate::ApplySideEffectChecks(
    Handle<BytecodeArray> bytecode_array) {
  for (interpreter::BytecodeArrayIterator it(bytecode_array); !it.done();
       it.Advance()) {
    interpreter::Bytecode bytecode = it.current_bytecode();
1127
    if (BytecodeRequiresRuntimeCheck(bytecode)) it.ApplyDebugBreak();
1128 1129 1130
  }
}

1131 1132
}  // namespace internal
}  // namespace v8