/ interpreter / Interpreter.cpp
Interpreter.cpp
   1  /*
   2   * Copyright (C) 2008-2020 Apple Inc. All rights reserved.
   3   * Copyright (C) 2008 Cameron Zwarich <cwzwarich@uwaterloo.ca>
   4   *
   5   * Redistribution and use in source and binary forms, with or without
   6   * modification, are permitted provided that the following conditions
   7   * are met:
   8   *
   9   * 1.  Redistributions of source code must retain the above copyright
  10   *     notice, this list of conditions and the following disclaimer.
  11   * 2.  Redistributions in binary form must reproduce the above copyright
  12   *     notice, this list of conditions and the following disclaimer in the
  13   *     documentation and/or other materials provided with the distribution.
  14   * 3.  Neither the name of Apple Inc. ("Apple") nor the names of
  15   *     its contributors may be used to endorse or promote products derived
  16   *     from this software without specific prior written permission.
  17   *
  18   * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
  19   * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  20   * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  21   * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
  22   * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  23   * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  24   * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  25   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  26   * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  27   * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  28   */
  29  
  30  #include "config.h"
  31  #include "Interpreter.h"
  32  
  33  #include "BatchedTransitionOptimizer.h"
  34  #include "Bytecodes.h"
  35  #include "CallFrameClosure.h"
  36  #include "CatchScope.h"
  37  #include "CheckpointOSRExitSideState.h"
  38  #include "CodeBlock.h"
  39  #include "DirectArguments.h"
  40  #include "Debugger.h"
  41  #include "DirectEvalCodeCache.h"
  42  #include "EvalCodeBlock.h"
  43  #include "ExecutableBaseInlines.h"
  44  #include "FrameTracers.h"
  45  #include "InterpreterInlines.h"
  46  #include "JITCodeInlines.h"
  47  #include "JSArrayInlines.h"
  48  #include "JSCInlines.h"
  49  #include "JSImmutableButterfly.h"
  50  #include "JSLexicalEnvironment.h"
  51  #include "JSModuleEnvironment.h"
  52  #include "JSString.h"
  53  #include "LLIntThunks.h"
  54  #include "LiteralParser.h"
  55  #include "ModuleProgramCodeBlock.h"
  56  #include "ProgramCodeBlock.h"
  57  #include "ProtoCallFrameInlines.h"
  58  #include "Register.h"
  59  #include "RegisterAtOffsetList.h"
  60  #include "ScopedArguments.h"
  61  #include "StackFrame.h"
  62  #include "StackVisitor.h"
  63  #include "StrictEvalActivation.h"
  64  #include "VMEntryScope.h"
  65  #include "VMInlines.h"
  66  #include "VirtualRegister.h"
  67  #include <stdio.h>
  68  #include <wtf/NeverDestroyed.h>
  69  #include <wtf/Scope.h>
  70  #include <wtf/StdLibExtras.h>
  71  #include <wtf/text/StringBuilder.h>
  72  
  73  #if ENABLE(WEBASSEMBLY)
  74  #include "WasmContextInlines.h"
  75  #include "WebAssemblyFunction.h"
  76  #endif
  77  
  78  namespace JSC {
  79  
  80  JSValue eval(JSGlobalObject* globalObject, CallFrame* callFrame, ECMAMode ecmaMode)
  81  {
  82      VM& vm = globalObject->vm();
  83      auto scope = DECLARE_THROW_SCOPE(vm);
  84  
  85      auto clobberizeValidator = makeScopeExit([&] {
  86          vm.didEnterVM = true;
  87      });
  88  
  89      if (!callFrame->argumentCount())
  90          return jsUndefined();
  91  
  92      JSValue program = callFrame->argument(0);
  93      if (!program.isString())
  94          return program;
  95  
  96      TopCallFrameSetter topCallFrame(vm, callFrame);
  97      if (!globalObject->evalEnabled()) {
  98          throwException(globalObject, scope, createEvalError(globalObject, globalObject->evalDisabledErrorMessage()));
  99          return jsUndefined();
 100      }
 101      String programSource = asString(program)->value(globalObject);
 102      RETURN_IF_EXCEPTION(scope, JSValue());
 103      
 104      CallFrame* callerFrame = callFrame->callerFrame();
 105      CallSiteIndex callerCallSiteIndex = callerFrame->callSiteIndex();
 106      CodeBlock* callerCodeBlock = callerFrame->codeBlock();
 107      JSScope* callerScopeChain = callerFrame->uncheckedR(callerCodeBlock->scopeRegister()).Register::scope();
 108      UnlinkedCodeBlock* callerUnlinkedCodeBlock = callerCodeBlock->unlinkedCodeBlock();
 109  
 110      bool isArrowFunctionContext = callerUnlinkedCodeBlock->isArrowFunction() || callerUnlinkedCodeBlock->isArrowFunctionContext();
 111  
 112      DerivedContextType derivedContextType = callerUnlinkedCodeBlock->derivedContextType();
 113      if (!isArrowFunctionContext && callerUnlinkedCodeBlock->isClassContext()) {
 114          derivedContextType = callerUnlinkedCodeBlock->isConstructor()
 115              ? DerivedContextType::DerivedConstructorContext
 116              : DerivedContextType::DerivedMethodContext;
 117      }
 118  
 119      EvalContextType evalContextType;
 120      if (callerUnlinkedCodeBlock->parseMode() == SourceParseMode::ClassFieldInitializerMode)
 121          evalContextType = EvalContextType::InstanceFieldEvalContext;
 122      else if (isFunctionParseMode(callerUnlinkedCodeBlock->parseMode()))
 123          evalContextType = EvalContextType::FunctionEvalContext;
 124      else if (callerUnlinkedCodeBlock->codeType() == EvalCode)
 125          evalContextType = callerUnlinkedCodeBlock->evalContextType();
 126      else
 127          evalContextType = EvalContextType::None;
 128  
 129      DirectEvalExecutable* eval = callerCodeBlock->directEvalCodeCache().tryGet(programSource, callerCallSiteIndex);
 130      if (!eval) {
 131          if (!ecmaMode.isStrict()) {
 132              if (programSource.is8Bit()) {
 133                  LiteralParser<LChar> preparser(globalObject, programSource.characters8(), programSource.length(), NonStrictJSON, callerCodeBlock);
 134                  if (JSValue parsedObject = preparser.tryLiteralParse())
 135                      RELEASE_AND_RETURN(scope, parsedObject);
 136  
 137              } else {
 138                  LiteralParser<UChar> preparser(globalObject, programSource.characters16(), programSource.length(), NonStrictJSON, callerCodeBlock);
 139                  if (JSValue parsedObject = preparser.tryLiteralParse())
 140                      RELEASE_AND_RETURN(scope, parsedObject);
 141  
 142              }
 143              RETURN_IF_EXCEPTION(scope, JSValue());
 144          }
 145          
 146          TDZEnvironment variablesUnderTDZ;
 147          VariableEnvironment privateNames;
 148          JSScope::collectClosureVariablesUnderTDZ(callerScopeChain, variablesUnderTDZ, privateNames);
 149          eval = DirectEvalExecutable::create(globalObject, makeSource(programSource, callerCodeBlock->source().provider()->sourceOrigin()), derivedContextType, callerUnlinkedCodeBlock->needsClassFieldInitializer(), isArrowFunctionContext, callerCodeBlock->ownerExecutable()->isInsideOrdinaryFunction(), evalContextType, &variablesUnderTDZ, &privateNames, ecmaMode);
 150          EXCEPTION_ASSERT(!!scope.exception() == !eval);
 151          if (!eval)
 152              return jsUndefined();
 153  
 154          callerCodeBlock->directEvalCodeCache().set(globalObject, callerCodeBlock, programSource, callerCallSiteIndex, eval);
 155      }
 156  
 157      JSValue thisValue = callerFrame->thisValue();
 158      Interpreter* interpreter = vm.interpreter;
 159      RELEASE_AND_RETURN(scope, interpreter->execute(eval, globalObject, thisValue, callerScopeChain));
 160  }
 161  
 162  unsigned sizeOfVarargs(JSGlobalObject* globalObject, JSValue arguments, uint32_t firstVarArgOffset)
 163  {
 164      VM& vm = globalObject->vm();
 165      auto scope = DECLARE_THROW_SCOPE(vm);
 166  
 167      if (UNLIKELY(!arguments.isCell())) {
 168          if (arguments.isUndefinedOrNull())
 169              return 0;
 170          
 171          throwException(globalObject, scope, createInvalidFunctionApplyParameterError(globalObject, arguments));
 172          return 0;
 173      }
 174      
 175      JSCell* cell = arguments.asCell();
 176      unsigned length;
 177      switch (cell->type()) {
 178      case DirectArgumentsType:
 179          length = jsCast<DirectArguments*>(cell)->length(globalObject);
 180          break;
 181      case ScopedArgumentsType:
 182          length = jsCast<ScopedArguments*>(cell)->length(globalObject);
 183          break;
 184      case JSImmutableButterflyType:
 185          length = jsCast<JSImmutableButterfly*>(cell)->length();
 186          break;
 187      case StringType:
 188      case SymbolType:
 189      case HeapBigIntType:
 190          throwException(globalObject, scope, createInvalidFunctionApplyParameterError(globalObject,  arguments));
 191          return 0;
 192          
 193      default:
 194          RELEASE_ASSERT(arguments.isObject());
 195          length = clampToUnsigned(toLength(globalObject, jsCast<JSObject*>(cell)));
 196          break;
 197      }
 198      RETURN_IF_EXCEPTION(scope, 0);
 199      
 200      if (length > maxArguments)
 201          throwStackOverflowError(globalObject, scope);
 202  
 203      if (length >= firstVarArgOffset)
 204          length -= firstVarArgOffset;
 205      else
 206          length = 0;
 207      
 208      return length;
 209  }
 210  
 211  unsigned sizeFrameForForwardArguments(JSGlobalObject* globalObject, CallFrame* callFrame, VM& vm, unsigned numUsedStackSlots)
 212  {
 213      auto scope = DECLARE_THROW_SCOPE(vm);
 214  
 215      unsigned length = callFrame->argumentCount();
 216      CallFrame* calleeFrame = calleeFrameForVarargs(callFrame, numUsedStackSlots, length + 1);
 217      if (UNLIKELY(!vm.ensureStackCapacityFor(calleeFrame->registers())))
 218          throwStackOverflowError(globalObject, scope);
 219  
 220      return length;
 221  }
 222  
 223  unsigned sizeFrameForVarargs(JSGlobalObject* globalObject, CallFrame* callFrame, VM& vm, JSValue arguments, unsigned numUsedStackSlots, uint32_t firstVarArgOffset)
 224  {
 225      auto scope = DECLARE_THROW_SCOPE(vm);
 226  
 227      unsigned length = sizeOfVarargs(globalObject, arguments, firstVarArgOffset);
 228      RETURN_IF_EXCEPTION(scope, 0);
 229  
 230      CallFrame* calleeFrame = calleeFrameForVarargs(callFrame, numUsedStackSlots, length + 1);
 231      if (UNLIKELY(length > maxArguments || !vm.ensureStackCapacityFor(calleeFrame->registers()))) {
 232          throwStackOverflowError(globalObject, scope);
 233          return 0;
 234      }
 235      
 236      return length;
 237  }
 238  
 239  void loadVarargs(JSGlobalObject* globalObject, JSValue* firstElementDest, JSValue arguments, uint32_t offset, uint32_t length)
 240  {
 241      if (UNLIKELY(!arguments.isCell()) || !length)
 242          return;
 243  
 244      VM& vm = globalObject->vm();
 245      auto scope = DECLARE_THROW_SCOPE(vm);
 246      JSCell* cell = arguments.asCell();
 247  
 248      switch (cell->type()) {
 249      case DirectArgumentsType:
 250          scope.release();
 251          jsCast<DirectArguments*>(cell)->copyToArguments(globalObject, firstElementDest, offset, length);
 252          return;
 253      case ScopedArgumentsType:
 254          scope.release();
 255          jsCast<ScopedArguments*>(cell)->copyToArguments(globalObject, firstElementDest, offset, length);
 256          return;
 257      case JSImmutableButterflyType:
 258          scope.release();
 259          jsCast<JSImmutableButterfly*>(cell)->copyToArguments(globalObject, firstElementDest, offset, length);
 260          return; 
 261      default: {
 262          ASSERT(arguments.isObject());
 263          JSObject* object = jsCast<JSObject*>(cell);
 264          if (isJSArray(object)) {
 265              scope.release();
 266              jsCast<JSArray*>(object)->copyToArguments(globalObject, firstElementDest, offset, length);
 267              return;
 268          }
 269          unsigned i;
 270          for (i = 0; i < length && object->canGetIndexQuickly(i + offset); ++i)
 271              firstElementDest[i] = object->getIndexQuickly(i + offset);
 272          for (; i < length; ++i) {
 273              JSValue value = object->get(globalObject, i + offset);
 274              RETURN_IF_EXCEPTION(scope, void());
 275              firstElementDest[i] = value;
 276          }
 277          return;
 278      } }
 279  }
 280  
 281  void setupVarargsFrame(JSGlobalObject* globalObject, CallFrame* callFrame, CallFrame* newCallFrame, JSValue arguments, uint32_t offset, uint32_t length)
 282  {
 283      VirtualRegister calleeFrameOffset(newCallFrame - callFrame);
 284      
 285      loadVarargs(
 286          globalObject,
 287          bitwise_cast<JSValue*>(&callFrame->r(calleeFrameOffset + CallFrame::argumentOffset(0))),
 288          arguments, offset, length);
 289      
 290      newCallFrame->setArgumentCountIncludingThis(length + 1);
 291  }
 292  
 293  void setupVarargsFrameAndSetThis(JSGlobalObject* globalObject, CallFrame* callFrame, CallFrame* newCallFrame, JSValue thisValue, JSValue arguments, uint32_t firstVarArgOffset, uint32_t length)
 294  {
 295      setupVarargsFrame(globalObject, callFrame, newCallFrame, arguments, firstVarArgOffset, length);
 296      newCallFrame->setThisValue(thisValue);
 297  }
 298  
 299  void setupForwardArgumentsFrame(JSGlobalObject*, CallFrame* execCaller, CallFrame* execCallee, uint32_t length)
 300  {
 301      ASSERT(length == execCaller->argumentCount());
 302      unsigned offset = execCaller->argumentOffset(0) * sizeof(Register);
 303      memcpy(reinterpret_cast<char*>(execCallee) + offset, reinterpret_cast<char*>(execCaller) + offset, length * sizeof(Register));
 304      execCallee->setArgumentCountIncludingThis(length + 1);
 305  }
 306  
 307  void setupForwardArgumentsFrameAndSetThis(JSGlobalObject* globalObject, CallFrame* execCaller, CallFrame* execCallee, JSValue thisValue, uint32_t length)
 308  {
 309      setupForwardArgumentsFrame(globalObject, execCaller, execCallee, length);
 310      execCallee->setThisValue(thisValue);
 311  }
 312  
 313      
 314  
 315  Interpreter::Interpreter(VM& vm)
 316      : m_vm(vm)
 317  #if ENABLE(C_LOOP)
 318      , m_cloopStack(vm)
 319  #endif
 320  {
 321  #if ASSERT_ENABLED
 322      static std::once_flag assertOnceKey;
 323      std::call_once(assertOnceKey, [] {
 324          for (unsigned i = 0; i < NUMBER_OF_BYTECODE_IDS; ++i) {
 325              OpcodeID opcodeID = static_cast<OpcodeID>(i);
 326              RELEASE_ASSERT(getOpcodeID(getOpcode(opcodeID)) == opcodeID);
 327          }
 328      });
 329  #endif // ASSERT_ENABLED
 330  }
 331  
 332  Interpreter::~Interpreter()
 333  {
 334  }
 335  
 336  #if ENABLE(COMPUTED_GOTO_OPCODES)
 337  #if !ENABLE(LLINT_EMBEDDED_OPCODE_ID) || ASSERT_ENABLED
 338  HashMap<Opcode, OpcodeID>& Interpreter::opcodeIDTable()
 339  {
 340      static LazyNeverDestroyed<HashMap<Opcode, OpcodeID>> opcodeIDTable;
 341  
 342      static std::once_flag initializeKey;
 343      std::call_once(initializeKey, [&] {
 344          opcodeIDTable.construct();
 345          const Opcode* opcodeTable = LLInt::opcodeMap();
 346          for (unsigned i = 0; i < NUMBER_OF_BYTECODE_IDS; ++i)
 347              opcodeIDTable->add(opcodeTable[i], static_cast<OpcodeID>(i));
 348      });
 349  
 350      return opcodeIDTable;
 351  }
 352  #endif // !ENABLE(LLINT_EMBEDDED_OPCODE_ID) || ASSERT_ENABLED
 353  #endif // ENABLE(COMPUTED_GOTO_OPCODES)
 354  
 355  #if ASSERT_ENABLED
 356  bool Interpreter::isOpcode(Opcode opcode)
 357  {
 358  #if ENABLE(COMPUTED_GOTO_OPCODES)
 359      return opcode != HashTraits<Opcode>::emptyValue()
 360          && !HashTraits<Opcode>::isDeletedValue(opcode)
 361          && opcodeIDTable().contains(opcode);
 362  #else
 363      return opcode >= 0 && opcode <= op_end;
 364  #endif
 365  }
 366  #endif // ASSERT_ENABLED
 367  
 368  class GetStackTraceFunctor {
 369  public:
 370      GetStackTraceFunctor(VM& vm, JSCell* owner, Vector<StackFrame>& results, size_t framesToSkip, size_t capacity)
 371          : m_vm(vm)
 372          , m_owner(owner)
 373          , m_results(results)
 374          , m_framesToSkip(framesToSkip)
 375          , m_remainingCapacityForFrameCapture(capacity)
 376      {
 377          m_results.reserveInitialCapacity(capacity);
 378      }
 379  
 380      StackVisitor::Status operator()(StackVisitor& visitor) const
 381      {
 382          if (m_framesToSkip > 0) {
 383              m_framesToSkip--;
 384              return StackVisitor::Continue;
 385          }
 386  
 387          if (m_remainingCapacityForFrameCapture) {
 388              if (visitor->isWasmFrame()) {
 389                  m_results.append(StackFrame(visitor->wasmFunctionIndexOrName()));
 390              } else if (!!visitor->codeBlock() && !visitor->codeBlock()->unlinkedCodeBlock()->isBuiltinFunction()) {
 391                  m_results.append(
 392                      StackFrame(m_vm, m_owner, visitor->callee().asCell(), visitor->codeBlock(), visitor->bytecodeIndex()));
 393              } else {
 394                  m_results.append(
 395                      StackFrame(m_vm, m_owner, visitor->callee().asCell()));
 396              }
 397      
 398              m_remainingCapacityForFrameCapture--;
 399              return StackVisitor::Continue;
 400          }
 401          return StackVisitor::Done;
 402      }
 403  
 404  private:
 405      VM& m_vm;
 406      JSCell* m_owner;
 407      Vector<StackFrame>& m_results;
 408      mutable size_t m_framesToSkip;
 409      mutable size_t m_remainingCapacityForFrameCapture;
 410  };
 411  
 412  void Interpreter::getStackTrace(JSCell* owner, Vector<StackFrame>& results, size_t framesToSkip, size_t maxStackSize)
 413  {
 414      DisallowGC disallowGC;
 415      VM& vm = m_vm;
 416      CallFrame* callFrame = vm.topCallFrame;
 417      if (!callFrame || !maxStackSize)
 418          return;
 419  
 420      size_t framesCount = 0;
 421      size_t maxFramesCountNeeded = maxStackSize + framesToSkip;
 422      StackVisitor::visit(callFrame, vm, [&] (StackVisitor&) -> StackVisitor::Status {
 423          if (++framesCount < maxFramesCountNeeded)
 424              return StackVisitor::Continue;
 425          return StackVisitor::Done;
 426      });
 427      if (framesCount <= framesToSkip)
 428          return;
 429  
 430      framesCount -= framesToSkip;
 431      framesCount = std::min(maxStackSize, framesCount);
 432  
 433      GetStackTraceFunctor functor(vm, owner, results, framesToSkip, framesCount);
 434      StackVisitor::visit(callFrame, vm, functor);
 435      ASSERT(results.size() == results.capacity());
 436  }
 437  
 438  String Interpreter::stackTraceAsString(VM& vm, const Vector<StackFrame>& stackTrace)
 439  {
 440      // FIXME: JSStringJoiner could be more efficient than StringBuilder here.
 441      StringBuilder builder;
 442      for (unsigned i = 0; i < stackTrace.size(); i++) {
 443          builder.append(String(stackTrace[i].toString(vm)));
 444          if (i != stackTrace.size() - 1)
 445              builder.append('\n');
 446      }
 447      return builder.toString();
 448  }
 449  
 450  ALWAYS_INLINE static HandlerInfo* findExceptionHandler(StackVisitor& visitor, CodeBlock* codeBlock, RequiredHandler requiredHandler)
 451  {
 452      ASSERT(codeBlock);
 453  #if ENABLE(DFG_JIT)
 454      ASSERT(!visitor->isInlinedFrame());
 455  #endif
 456  
 457      CallFrame* callFrame = visitor->callFrame();
 458      unsigned exceptionHandlerIndex;
 459      if (JITCode::isOptimizingJIT(codeBlock->jitType()))
 460          exceptionHandlerIndex = callFrame->callSiteIndex().bits();
 461      else
 462          exceptionHandlerIndex = callFrame->bytecodeIndex().offset();
 463  
 464      return codeBlock->handlerForIndex(exceptionHandlerIndex, requiredHandler);
 465  }
 466  
 467  class GetCatchHandlerFunctor {
 468  public:
 469      GetCatchHandlerFunctor()
 470          : m_handler(nullptr)
 471      {
 472      }
 473  
 474      HandlerInfo* handler() { return m_handler; }
 475  
 476      StackVisitor::Status operator()(StackVisitor& visitor) const
 477      {
 478          visitor.unwindToMachineCodeBlockFrame();
 479  
 480          CodeBlock* codeBlock = visitor->codeBlock();
 481          if (!codeBlock)
 482              return StackVisitor::Continue;
 483  
 484          m_handler = findExceptionHandler(visitor, codeBlock, RequiredHandler::CatchHandler);
 485          if (m_handler)
 486              return StackVisitor::Done;
 487  
 488          return StackVisitor::Continue;
 489      }
 490  
 491  private:
 492      mutable HandlerInfo* m_handler;
 493  };
 494  
 495  ALWAYS_INLINE static void notifyDebuggerOfUnwinding(VM& vm, CallFrame* callFrame)
 496  {
 497      JSGlobalObject* globalObject = callFrame->lexicalGlobalObject(vm);
 498      auto catchScope = DECLARE_CATCH_SCOPE(vm);
 499      if (Debugger* debugger = globalObject->debugger()) {
 500          SuspendExceptionScope scope(&vm);
 501          if (callFrame->isAnyWasmCallee()
 502              || (callFrame->callee().isCell() && callFrame->callee().asCell()->inherits<JSFunction>(vm)))
 503              debugger->unwindEvent(callFrame);
 504          else
 505              debugger->didExecuteProgram(callFrame);
 506          catchScope.assertNoException();
 507      }
 508  }
 509  
 510  class UnwindFunctor {
 511  public:
 512      UnwindFunctor(VM& vm, CallFrame*& callFrame, bool isTermination, CodeBlock*& codeBlock, HandlerInfo*& handler)
 513          : m_vm(vm)
 514          , m_callFrame(callFrame)
 515          , m_isTermination(isTermination)
 516          , m_codeBlock(codeBlock)
 517          , m_handler(handler)
 518      {
 519      }
 520  
 521      StackVisitor::Status operator()(StackVisitor& visitor) const
 522      {
 523          visitor.unwindToMachineCodeBlockFrame();
 524          m_callFrame = visitor->callFrame();
 525          m_codeBlock = visitor->codeBlock();
 526  
 527          m_handler = nullptr;
 528          if (m_codeBlock) {
 529              if (!m_isTermination) {
 530                  m_handler = findExceptionHandler(visitor, m_codeBlock, RequiredHandler::AnyHandler);
 531                  if (m_handler)
 532                      return StackVisitor::Done;
 533              }
 534          }
 535  
 536  #if ENABLE(WEBASSEMBLY)
 537          if (visitor->callee().isCell()) {
 538              if (auto* jsToWasmICCallee = jsDynamicCast<JSToWasmICCallee*>(m_vm, visitor->callee().asCell()))
 539                  m_vm.wasmContext.store(jsToWasmICCallee->function()->previousInstance(m_callFrame), m_vm.softStackLimit());
 540          }
 541  #endif
 542  
 543          notifyDebuggerOfUnwinding(m_vm, m_callFrame);
 544  
 545          copyCalleeSavesToEntryFrameCalleeSavesBuffer(visitor);
 546  
 547          bool shouldStopUnwinding = visitor->callerIsEntryFrame();
 548          if (shouldStopUnwinding)
 549              return StackVisitor::Done;
 550  
 551          return StackVisitor::Continue;
 552      }
 553  
 554  private:
 555      void copyCalleeSavesToEntryFrameCalleeSavesBuffer(StackVisitor& visitor) const
 556      {
 557  #if ENABLE(ASSEMBLER)
 558          Optional<RegisterAtOffsetList> currentCalleeSaves = visitor->calleeSaveRegistersForUnwinding();
 559  
 560          if (!currentCalleeSaves)
 561              return;
 562  
 563          RegisterAtOffsetList* allCalleeSaves = RegisterSet::vmCalleeSaveRegisterOffsets();
 564          RegisterSet dontCopyRegisters = RegisterSet::stackRegisters();
 565          CPURegister* frame = reinterpret_cast<CPURegister*>(m_callFrame->registers());
 566  
 567          unsigned registerCount = currentCalleeSaves->size();
 568          VMEntryRecord* record = vmEntryRecord(m_vm.topEntryFrame);
 569          for (unsigned i = 0; i < registerCount; i++) {
 570              RegisterAtOffset currentEntry = currentCalleeSaves->at(i);
 571              if (dontCopyRegisters.get(currentEntry.reg()))
 572                  continue;
 573              RegisterAtOffset* calleeSavesEntry = allCalleeSaves->find(currentEntry.reg());
 574              
 575              record->calleeSaveRegistersBuffer[calleeSavesEntry->offsetAsIndex()] = *(frame + currentEntry.offsetAsIndex());
 576          }
 577  #else
 578          UNUSED_PARAM(visitor);
 579  #endif
 580      }
 581  
 582      VM& m_vm;
 583      CallFrame*& m_callFrame;
 584      bool m_isTermination;
 585      CodeBlock*& m_codeBlock;
 586      HandlerInfo*& m_handler;
 587  };
 588  
 589  NEVER_INLINE HandlerInfo* Interpreter::unwind(VM& vm, CallFrame*& callFrame, Exception* exception)
 590  {
 591      auto scope = DECLARE_CATCH_SCOPE(vm);
 592  
 593      ASSERT(reinterpret_cast<void*>(callFrame) != vm.topEntryFrame);
 594      CodeBlock* codeBlock = callFrame->codeBlock();
 595  
 596      JSValue exceptionValue = exception->value();
 597      ASSERT(!exceptionValue.isEmpty());
 598      ASSERT(!exceptionValue.isCell() || exceptionValue.asCell());
 599      // This shouldn't be possible (hence the assertions), but we're already in the slowest of
 600      // slow cases, so let's harden against it anyway to be safe.
 601      if (exceptionValue.isEmpty() || (exceptionValue.isCell() && !exceptionValue.asCell()))
 602          exceptionValue = jsNull();
 603  
 604      EXCEPTION_ASSERT_UNUSED(scope, scope.exception());
 605  
 606      // Calculate an exception handler vPC, unwinding call frames as necessary.
 607      HandlerInfo* handler = nullptr;
 608      UnwindFunctor functor(vm, callFrame, isTerminatedExecutionException(vm, exception), codeBlock, handler);
 609      StackVisitor::visit<StackVisitor::TerminateIfTopEntryFrameIsEmpty>(callFrame, vm, functor);
 610      if (vm.hasCheckpointOSRSideState())
 611          vm.popAllCheckpointOSRSideStateUntil(callFrame);
 612  
 613      if (!handler)
 614          return nullptr;
 615  
 616      return handler;
 617  }
 618  
 619  void Interpreter::notifyDebuggerOfExceptionToBeThrown(VM& vm, JSGlobalObject* globalObject, CallFrame* callFrame, Exception* exception)
 620  {
 621      Debugger* debugger = globalObject->debugger();
 622      if (debugger && debugger->needsExceptionCallbacks() && !exception->didNotifyInspectorOfThrow()) {
 623          // This code assumes that if the debugger is enabled then there is no inlining.
 624          // If that assumption turns out to be false then we'll ignore the inlined call
 625          // frames.
 626          // https://bugs.webkit.org/show_bug.cgi?id=121754
 627  
 628          bool hasCatchHandler;
 629          bool isTermination = isTerminatedExecutionException(vm, exception);
 630          if (isTermination)
 631              hasCatchHandler = false;
 632          else {
 633              GetCatchHandlerFunctor functor;
 634              StackVisitor::visit(callFrame, vm, functor);
 635              HandlerInfo* handler = functor.handler();
 636              ASSERT(!handler || handler->isCatchHandler());
 637              hasCatchHandler = !!handler;
 638          }
 639  
 640          debugger->exception(globalObject, callFrame, exception->value(), hasCatchHandler);
 641      }
 642      exception->setDidNotifyInspectorOfThrow();
 643  }
 644  
 645  JSValue Interpreter::executeProgram(const SourceCode& source, JSGlobalObject*, JSObject* thisObj)
 646  {
 647      JSScope* scope = thisObj->globalObject()->globalScope();
 648      VM& vm = scope->vm();
 649      auto throwScope = DECLARE_THROW_SCOPE(vm);
 650      JSGlobalObject* globalObject = scope->globalObject(vm);
 651      JSCallee* globalCallee = globalObject->globalCallee();
 652  
 653      auto clobberizeValidator = makeScopeExit([&] {
 654          vm.didEnterVM = true;
 655      });
 656  
 657      ProgramExecutable* program = ProgramExecutable::create(globalObject, source);
 658      EXCEPTION_ASSERT(throwScope.exception() || program);
 659      RETURN_IF_EXCEPTION(throwScope, { });
 660  
 661      throwScope.assertNoException();
 662      ASSERT(!vm.isCollectorBusyOnCurrentThread());
 663      RELEASE_ASSERT(vm.currentThreadIsHoldingAPILock());
 664      if (vm.isCollectorBusyOnCurrentThread())
 665          return jsNull();
 666  
 667      if (UNLIKELY(!vm.isSafeToRecurseSoft()))
 668          return checkedReturn(throwStackOverflowError(globalObject, throwScope));
 669  
 670      // First check if the "program" is actually just a JSON object. If so,
 671      // we'll handle the JSON object here. Else, we'll handle real JS code
 672      // below at failedJSONP.
 673  
 674      Vector<JSONPData> JSONPData;
 675      bool parseResult;
 676      StringView programSource = program->source().view();
 677      if (programSource.isNull())
 678          return jsUndefined();
 679      if (programSource.is8Bit()) {
 680          LiteralParser<LChar> literalParser(globalObject, programSource.characters8(), programSource.length(), JSONP);
 681          parseResult = literalParser.tryJSONPParse(JSONPData, globalObject->globalObjectMethodTable()->supportsRichSourceInfo(globalObject));
 682      } else {
 683          LiteralParser<UChar> literalParser(globalObject, programSource.characters16(), programSource.length(), JSONP);
 684          parseResult = literalParser.tryJSONPParse(JSONPData, globalObject->globalObjectMethodTable()->supportsRichSourceInfo(globalObject));
 685      }
 686  
 687      RETURN_IF_EXCEPTION(throwScope, { });
 688      if (parseResult) {
 689          JSValue result;
 690          for (unsigned entry = 0; entry < JSONPData.size(); entry++) {
 691              Vector<JSONPPathEntry> JSONPPath;
 692              JSONPPath.swap(JSONPData[entry].m_path);
 693              JSValue JSONPValue = JSONPData[entry].m_value.get();
 694              if (JSONPPath.size() == 1 && JSONPPath[0].m_type == JSONPPathEntryTypeDeclareVar) {
 695                  globalObject->addVar(globalObject, JSONPPath[0].m_pathEntryName);
 696                  RETURN_IF_EXCEPTION(throwScope, { });
 697                  PutPropertySlot slot(globalObject);
 698                  globalObject->methodTable(vm)->put(globalObject, globalObject, JSONPPath[0].m_pathEntryName, JSONPValue, slot);
 699                  RETURN_IF_EXCEPTION(throwScope, { });
 700                  result = jsUndefined();
 701                  continue;
 702              }
 703              JSValue baseObject(globalObject);
 704              for (unsigned i = 0; i < JSONPPath.size() - 1; i++) {
 705                  ASSERT(JSONPPath[i].m_type != JSONPPathEntryTypeDeclareVar);
 706                  switch (JSONPPath[i].m_type) {
 707                  case JSONPPathEntryTypeDot: {
 708                      if (i == 0) {
 709                          RELEASE_ASSERT(baseObject == globalObject);
 710  
 711                          auto doGet = [&] (JSSegmentedVariableObject* scope) {
 712                              PropertySlot slot(scope, PropertySlot::InternalMethodType::Get);
 713                              if (scope->getPropertySlot(globalObject, JSONPPath[i].m_pathEntryName, slot))
 714                                  return slot.getValue(globalObject, JSONPPath[i].m_pathEntryName);
 715                              return JSValue();
 716                          };
 717  
 718                          JSValue result = doGet(globalObject->globalLexicalEnvironment());
 719                          RETURN_IF_EXCEPTION(throwScope, JSValue());
 720                          if (result) {
 721                              baseObject = result;
 722                              continue;
 723                          }
 724  
 725                          result = doGet(globalObject);
 726                          RETURN_IF_EXCEPTION(throwScope, JSValue());
 727                          if (result) {
 728                              baseObject = result;
 729                              continue;
 730                          }
 731  
 732                          if (entry)
 733                              return throwException(globalObject, throwScope, createUndefinedVariableError(globalObject, JSONPPath[i].m_pathEntryName));
 734                          goto failedJSONP;
 735                      }
 736  
 737                      baseObject = baseObject.get(globalObject, JSONPPath[i].m_pathEntryName);
 738                      RETURN_IF_EXCEPTION(throwScope, JSValue());
 739                      continue;
 740                  }
 741                  case JSONPPathEntryTypeLookup: {
 742                      baseObject = baseObject.get(globalObject, static_cast<unsigned>(JSONPPath[i].m_pathIndex));
 743                      RETURN_IF_EXCEPTION(throwScope, JSValue());
 744                      continue;
 745                  }
 746                  default:
 747                      RELEASE_ASSERT_NOT_REACHED();
 748                      return jsUndefined();
 749                  }
 750              }
 751  
 752              if (JSONPPath.size() == 1 && JSONPPath.last().m_type != JSONPPathEntryTypeLookup) {
 753                  RELEASE_ASSERT(baseObject == globalObject);
 754                  JSGlobalLexicalEnvironment* scope = globalObject->globalLexicalEnvironment();
 755                  if (scope->hasProperty(globalObject, JSONPPath.last().m_pathEntryName))
 756                      baseObject = scope;
 757                  RETURN_IF_EXCEPTION(throwScope, JSValue());
 758              }
 759  
 760              PutPropertySlot slot(baseObject);
 761              switch (JSONPPath.last().m_type) {
 762              case JSONPPathEntryTypeCall: {
 763                  JSValue function = baseObject.get(globalObject, JSONPPath.last().m_pathEntryName);
 764                  RETURN_IF_EXCEPTION(throwScope, JSValue());
 765                  auto callData = getCallData(vm, function);
 766                  if (callData.type == CallData::Type::None)
 767                      return throwException(globalObject, throwScope, createNotAFunctionError(globalObject, function));
 768                  MarkedArgumentBuffer jsonArg;
 769                  jsonArg.append(JSONPValue);
 770                  ASSERT(!jsonArg.hasOverflowed());
 771                  JSValue thisValue = JSONPPath.size() == 1 ? jsUndefined() : baseObject;
 772                  JSONPValue = JSC::call(globalObject, function, callData, thisValue, jsonArg);
 773                  RETURN_IF_EXCEPTION(throwScope, JSValue());
 774                  break;
 775              }
 776              case JSONPPathEntryTypeDot: {
 777                  baseObject.put(globalObject, JSONPPath.last().m_pathEntryName, JSONPValue, slot);
 778                  RETURN_IF_EXCEPTION(throwScope, JSValue());
 779                  break;
 780              }
 781              case JSONPPathEntryTypeLookup: {
 782                  baseObject.putByIndex(globalObject, JSONPPath.last().m_pathIndex, JSONPValue, slot.isStrictMode());
 783                  RETURN_IF_EXCEPTION(throwScope, JSValue());
 784                  break;
 785              }
 786              default:
 787                  RELEASE_ASSERT_NOT_REACHED();
 788                  return jsUndefined();
 789              }
 790              result = JSONPValue;
 791          }
 792          return result;
 793      }
 794  failedJSONP:
 795      // If we get here, then we have already proven that the script is not a JSON
 796      // object.
 797  
 798      VMEntryScope entryScope(vm, globalObject);
 799  
 800      // Compile source to bytecode if necessary:
 801      JSObject* error = program->initializeGlobalProperties(vm, globalObject, scope);
 802      EXCEPTION_ASSERT(!throwScope.exception() || !error);
 803      if (UNLIKELY(error))
 804          return checkedReturn(throwException(globalObject, throwScope, error));
 805  
 806      constexpr auto trapsMask = VMTraps::interruptingTraps();
 807      if (UNLIKELY(vm.needTrapHandling(trapsMask))) {
 808          vm.handleTraps(globalObject, vm.topCallFrame, trapsMask);
 809          RETURN_IF_EXCEPTION(throwScope, throwScope.exception());
 810      }
 811  
 812      if (scope->structure(vm)->isUncacheableDictionary())
 813          scope->flattenDictionaryObject(vm);
 814  
 815      ProgramCodeBlock* codeBlock;
 816      {
 817          CodeBlock* tempCodeBlock;
 818          Exception* error = program->prepareForExecution<ProgramExecutable>(vm, nullptr, scope, CodeForCall, tempCodeBlock);
 819          EXCEPTION_ASSERT(throwScope.exception() == error);
 820          if (UNLIKELY(error))
 821              return checkedReturn(error);
 822          codeBlock = jsCast<ProgramCodeBlock*>(tempCodeBlock);
 823          ASSERT(codeBlock->numParameters() == 1); // 1 parameter for 'this'.
 824      }
 825  
 826      RefPtr<JITCode> jitCode;
 827      ProtoCallFrame protoCallFrame;
 828      {
 829          DisallowGC disallowGC; // Ensure no GC happens. GC can replace CodeBlock in Executable.
 830          jitCode = program->generatedJITCode();
 831          protoCallFrame.init(codeBlock, globalObject, globalCallee, thisObj, 1);
 832      }
 833  
 834      // Execute the code:
 835      throwScope.release();
 836      ASSERT(jitCode == program->generatedJITCode().ptr());
 837      JSValue result = jitCode->execute(&vm, &protoCallFrame);
 838      return checkedReturn(result);
 839  }
 840  
 841  JSValue Interpreter::executeCall(JSGlobalObject* lexicalGlobalObject, JSObject* function, const CallData& callData, JSValue thisValue, const ArgList& args)
 842  {
 843      VM& vm = lexicalGlobalObject->vm();
 844      auto throwScope = DECLARE_THROW_SCOPE(vm);
 845  
 846      auto clobberizeValidator = makeScopeExit([&] {
 847          vm.didEnterVM = true;
 848      });
 849  
 850      throwScope.assertNoException();
 851      ASSERT(!vm.isCollectorBusyOnCurrentThread());
 852      if (vm.isCollectorBusyOnCurrentThread())
 853          return jsNull();
 854  
 855      bool isJSCall = (callData.type == CallData::Type::JS);
 856      JSScope* scope = nullptr;
 857      size_t argsCount = 1 + args.size(); // implicit "this" parameter
 858  
 859      JSGlobalObject* globalObject;
 860  
 861      if (isJSCall) {
 862          scope = callData.js.scope;
 863          globalObject = scope->globalObject(vm);
 864      } else {
 865          ASSERT(callData.type == CallData::Type::Native);
 866          globalObject = function->globalObject(vm);
 867      }
 868  
 869      VMEntryScope entryScope(vm, globalObject);
 870      if (UNLIKELY(!vm.isSafeToRecurseSoft() || args.size() > maxArguments))
 871          return checkedReturn(throwStackOverflowError(globalObject, throwScope));
 872  
 873      constexpr auto trapsMask = VMTraps::interruptingTraps();
 874      if (UNLIKELY(vm.needTrapHandling(trapsMask))) {
 875          vm.handleTraps(globalObject, vm.topCallFrame, trapsMask);
 876          RETURN_IF_EXCEPTION(throwScope, throwScope.exception());
 877      }
 878  
 879      CodeBlock* newCodeBlock = nullptr;
 880      if (isJSCall) {
 881          // Compile the callee:
 882          Exception* compileError = callData.js.functionExecutable->prepareForExecution<FunctionExecutable>(vm, jsCast<JSFunction*>(function), scope, CodeForCall, newCodeBlock);
 883          EXCEPTION_ASSERT(throwScope.exception() == compileError);
 884          if (UNLIKELY(!!compileError))
 885              return checkedReturn(compileError);
 886  
 887          ASSERT(!!newCodeBlock);
 888          newCodeBlock->m_shouldAlwaysBeInlined = false;
 889      }
 890  
 891      RefPtr<JITCode> jitCode;
 892      ProtoCallFrame protoCallFrame;
 893      {
 894          DisallowGC disallowGC; // Ensure no GC happens. GC can replace CodeBlock in Executable.
 895          if (isJSCall)
 896              jitCode = callData.js.functionExecutable->generatedJITCodeForCall();
 897          protoCallFrame.init(newCodeBlock, globalObject, function, thisValue, argsCount, args.data());
 898      }
 899  
 900      JSValue result;
 901      // Execute the code:
 902      if (isJSCall) {
 903          throwScope.release();
 904          ASSERT(jitCode == callData.js.functionExecutable->generatedJITCodeForCall().ptr());
 905          result = jitCode->execute(&vm, &protoCallFrame);
 906      } else {
 907          result = JSValue::decode(vmEntryToNative(callData.native.function.rawPointer(), &vm, &protoCallFrame));
 908          RETURN_IF_EXCEPTION(throwScope, JSValue());
 909      }
 910  
 911      return checkedReturn(result);
 912  }
 913  
 914  JSObject* Interpreter::executeConstruct(JSGlobalObject* lexicalGlobalObject, JSObject* constructor, const CallData& constructData, const ArgList& args, JSValue newTarget)
 915  {
 916      VM& vm = lexicalGlobalObject->vm();
 917      auto throwScope = DECLARE_THROW_SCOPE(vm);
 918  
 919      auto clobberizeValidator = makeScopeExit([&] {
 920          vm.didEnterVM = true;
 921      });
 922  
 923      throwScope.assertNoException();
 924      ASSERT(!vm.isCollectorBusyOnCurrentThread());
 925      // We throw in this case because we have to return something "valid" but we're
 926      // already in an invalid state.
 927      if (UNLIKELY(vm.isCollectorBusyOnCurrentThread())) {
 928          throwStackOverflowError(lexicalGlobalObject, throwScope);
 929          return nullptr;
 930      }
 931  
 932      bool isJSConstruct = (constructData.type == CallData::Type::JS);
 933      JSScope* scope = nullptr;
 934      size_t argsCount = 1 + args.size(); // implicit "this" parameter
 935  
 936      JSGlobalObject* globalObject;
 937  
 938      if (isJSConstruct) {
 939          scope = constructData.js.scope;
 940          globalObject = scope->globalObject(vm);
 941      } else {
 942          ASSERT(constructData.type == CallData::Type::Native);
 943          globalObject = constructor->globalObject(vm);
 944      }
 945  
 946      VMEntryScope entryScope(vm, globalObject);
 947      if (UNLIKELY(!vm.isSafeToRecurseSoft() || args.size() > maxArguments)) {
 948          throwStackOverflowError(globalObject, throwScope);
 949          return nullptr;
 950      }
 951  
 952      constexpr auto trapsMask = VMTraps::interruptingTraps();
 953      if (UNLIKELY(vm.needTrapHandling(trapsMask))) {
 954          vm.handleTraps(globalObject, vm.topCallFrame, trapsMask);
 955          RETURN_IF_EXCEPTION(throwScope, nullptr);
 956      }
 957  
 958      CodeBlock* newCodeBlock = nullptr;
 959      if (isJSConstruct) {
 960          // Compile the callee:
 961          Exception* compileError = constructData.js.functionExecutable->prepareForExecution<FunctionExecutable>(vm, jsCast<JSFunction*>(constructor), scope, CodeForConstruct, newCodeBlock);
 962          EXCEPTION_ASSERT(throwScope.exception() == compileError);
 963          if (UNLIKELY(!!compileError))
 964              return nullptr;
 965  
 966          ASSERT(!!newCodeBlock);
 967          newCodeBlock->m_shouldAlwaysBeInlined = false;
 968      }
 969  
 970      RefPtr<JITCode> jitCode;
 971      ProtoCallFrame protoCallFrame;
 972      {
 973          DisallowGC disallowGC; // Ensure no GC happens. GC can replace CodeBlock in Executable.
 974          if (isJSConstruct)
 975              jitCode = constructData.js.functionExecutable->generatedJITCodeForConstruct();
 976          protoCallFrame.init(newCodeBlock, globalObject, constructor, newTarget, argsCount, args.data());
 977      }
 978  
 979      JSValue result;
 980      // Execute the code.
 981      if (isJSConstruct) {
 982          ASSERT(jitCode == constructData.js.functionExecutable->generatedJITCodeForConstruct().ptr());
 983          result = jitCode->execute(&vm, &protoCallFrame);
 984      } else {
 985          result = JSValue::decode(vmEntryToNative(constructData.native.function.rawPointer(), &vm, &protoCallFrame));
 986  
 987          if (LIKELY(!throwScope.exception()))
 988              RELEASE_ASSERT(result.isObject());
 989      }
 990  
 991      RETURN_IF_EXCEPTION(throwScope, nullptr);
 992      ASSERT(result.isObject());
 993      return checkedReturn(asObject(result));
 994  }
 995  
 996  CallFrameClosure Interpreter::prepareForRepeatCall(FunctionExecutable* functionExecutable, CallFrame* callFrame, ProtoCallFrame* protoCallFrame, JSFunction* function, int argumentCountIncludingThis, JSScope* scope, const ArgList& args)
 997  {
 998      VM& vm = scope->vm();
 999      auto throwScope = DECLARE_THROW_SCOPE(vm);
1000      throwScope.assertNoException();
1001      
1002      if (vm.isCollectorBusyOnCurrentThread())
1003          return CallFrameClosure();
1004  
1005      // Compile the callee:
1006      CodeBlock* newCodeBlock;
1007      Exception* error = functionExecutable->prepareForExecution<FunctionExecutable>(vm, function, scope, CodeForCall, newCodeBlock);
1008      EXCEPTION_ASSERT(throwScope.exception() == error);
1009      if (UNLIKELY(error))
1010          return CallFrameClosure();
1011      newCodeBlock->m_shouldAlwaysBeInlined = false;
1012  
1013      size_t argsCount = argumentCountIncludingThis;
1014  
1015      protoCallFrame->init(newCodeBlock, function->globalObject(), function, jsUndefined(), argsCount, args.data());
1016      // Return the successful closure:
1017      CallFrameClosure result = { callFrame, protoCallFrame, function, functionExecutable, &vm, scope, newCodeBlock->numParameters(), argumentCountIncludingThis };
1018      return result;
1019  }
1020  
1021  JSValue Interpreter::execute(EvalExecutable* eval, JSGlobalObject* lexicalGlobalObject, JSValue thisValue, JSScope* scope)
1022  {
1023      VM& vm = scope->vm();
1024      auto throwScope = DECLARE_THROW_SCOPE(vm);
1025  
1026      auto clobberizeValidator = makeScopeExit([&] {
1027          vm.didEnterVM = true;
1028      });
1029  
1030      ASSERT_UNUSED(lexicalGlobalObject, &vm == &lexicalGlobalObject->vm());
1031      throwScope.assertNoException();
1032      ASSERT(!vm.isCollectorBusyOnCurrentThread());
1033      RELEASE_ASSERT(vm.currentThreadIsHoldingAPILock());
1034      if (vm.isCollectorBusyOnCurrentThread())
1035          return jsNull();
1036  
1037      JSGlobalObject* globalObject = scope->globalObject(vm);
1038      VMEntryScope entryScope(vm, globalObject);
1039      if (UNLIKELY(!vm.isSafeToRecurseSoft()))
1040          return checkedReturn(throwStackOverflowError(globalObject, throwScope));
1041  
1042      unsigned numVariables = eval->numVariables();
1043      unsigned numTopLevelFunctionDecls = eval->numTopLevelFunctionDecls();
1044      unsigned numFunctionHoistingCandidates = eval->numFunctionHoistingCandidates();
1045  
1046      JSScope* variableObject;
1047      if ((numVariables || numTopLevelFunctionDecls) && eval->isInStrictContext()) {
1048          scope = StrictEvalActivation::create(vm, globalObject->strictEvalActivationStructure(), scope);
1049          variableObject = scope;
1050      } else {
1051          for (JSScope* node = scope; ; node = node->next()) {
1052              RELEASE_ASSERT(node);
1053              if (node->isGlobalObject()) {
1054                  variableObject = node;
1055                  break;
1056              } 
1057              if (node->isJSLexicalEnvironment()) {
1058                  JSLexicalEnvironment* lexicalEnvironment = jsCast<JSLexicalEnvironment*>(node);
1059                  if (lexicalEnvironment->symbolTable()->scopeType() == SymbolTable::ScopeType::VarScope) {
1060                      variableObject = node;
1061                      break;
1062                  }
1063              }
1064          }
1065      }
1066  
1067      constexpr auto trapsMask = VMTraps::interruptingTraps();
1068      if (UNLIKELY(vm.needTrapHandling(trapsMask))) {
1069          vm.handleTraps(globalObject, vm.topCallFrame, trapsMask);
1070          RETURN_IF_EXCEPTION(throwScope, throwScope.exception());
1071      }
1072  
1073      auto loadCodeBlock = [&](Exception*& compileError) -> EvalCodeBlock* {
1074          CodeBlock* tempCodeBlock;
1075          compileError = eval->prepareForExecution<EvalExecutable>(vm, nullptr, scope, CodeForCall, tempCodeBlock);
1076          EXCEPTION_ASSERT(throwScope.exception() == compileError);
1077          if (UNLIKELY(!!compileError))
1078              return nullptr;
1079          return jsCast<EvalCodeBlock*>(tempCodeBlock);
1080      };
1081  
1082      EvalCodeBlock* codeBlock;
1083      {
1084          Exception* compileError = nullptr;
1085          codeBlock = loadCodeBlock(compileError);
1086          EXCEPTION_ASSERT(throwScope.exception() == compileError);
1087          if (UNLIKELY(!!compileError))
1088              return checkedReturn(compileError);
1089          ASSERT(codeBlock->numParameters() == 1); // 1 parameter for 'this'.
1090      }
1091      UnlinkedEvalCodeBlock* unlinkedCodeBlock = codeBlock->unlinkedEvalCodeBlock();
1092  
1093      // We can't declare a "var"/"function" that overwrites a global "let"/"const"/"class" in a sloppy-mode eval.
1094      if (variableObject->isGlobalObject() && !eval->isInStrictContext() && (numVariables || numTopLevelFunctionDecls)) {
1095          JSGlobalLexicalEnvironment* globalLexicalEnvironment = jsCast<JSGlobalObject*>(variableObject)->globalLexicalEnvironment();
1096          for (unsigned i = 0; i < numVariables; ++i) {
1097              const Identifier& ident = unlinkedCodeBlock->variable(i);
1098              PropertySlot slot(globalLexicalEnvironment, PropertySlot::InternalMethodType::VMInquiry, &vm);
1099              if (JSGlobalLexicalEnvironment::getOwnPropertySlot(globalLexicalEnvironment, globalObject, ident, slot)) {
1100                  return checkedReturn(throwTypeError(globalObject, throwScope, makeString("Can't create duplicate global variable in eval: '", String(ident.impl()), "'")));
1101              }
1102          }
1103  
1104          for (unsigned i = 0; i < numTopLevelFunctionDecls; ++i) {
1105              FunctionExecutable* function = codeBlock->functionDecl(i);
1106              PropertySlot slot(globalLexicalEnvironment, PropertySlot::InternalMethodType::VMInquiry, &vm);
1107              if (JSGlobalLexicalEnvironment::getOwnPropertySlot(globalLexicalEnvironment, globalObject, function->name(), slot)) {
1108                  return checkedReturn(throwTypeError(globalObject, throwScope, makeString("Can't create duplicate global variable in eval: '", String(function->name().impl()), "'")));
1109              }
1110          }
1111      }
1112  
1113      if (variableObject->structure(vm)->isUncacheableDictionary())
1114          variableObject->flattenDictionaryObject(vm);
1115  
1116      if (numVariables || numTopLevelFunctionDecls || numFunctionHoistingCandidates) {
1117          BatchedTransitionOptimizer optimizer(vm, variableObject);
1118          if (variableObject->next() && !eval->isInStrictContext())
1119              variableObject->globalObject(vm)->varInjectionWatchpoint()->fireAll(vm, "Executed eval, fired VarInjection watchpoint");
1120  
1121          for (unsigned i = 0; i < numVariables; ++i) {
1122              const Identifier& ident = unlinkedCodeBlock->variable(i);
1123              bool hasProperty = variableObject->hasProperty(globalObject, ident);
1124              RETURN_IF_EXCEPTION(throwScope, checkedReturn(throwScope.exception()));
1125              if (!hasProperty) {
1126                  PutPropertySlot slot(variableObject);
1127                  if (!variableObject->isExtensible(globalObject))
1128                      return checkedReturn(throwTypeError(globalObject, throwScope, NonExtensibleObjectPropertyDefineError));
1129                  variableObject->methodTable(vm)->put(variableObject, globalObject, ident, jsUndefined(), slot);
1130                  RETURN_IF_EXCEPTION(throwScope, checkedReturn(throwScope.exception()));
1131              }
1132          }
1133          
1134          if (eval->isInStrictContext()) {
1135              for (unsigned i = 0; i < numTopLevelFunctionDecls; ++i) {
1136                  FunctionExecutable* function = codeBlock->functionDecl(i);
1137                  PutPropertySlot slot(variableObject);
1138                  // We need create this variables because it will be used to emits code by bytecode generator
1139                  variableObject->methodTable(vm)->put(variableObject, globalObject, function->name(), jsUndefined(), slot);
1140                  RETURN_IF_EXCEPTION(throwScope, checkedReturn(throwScope.exception()));
1141              }
1142          } else {
1143              for (unsigned i = 0; i < numTopLevelFunctionDecls; ++i) {
1144                  FunctionExecutable* function = codeBlock->functionDecl(i);
1145                  JSValue resolvedScope = JSScope::resolveScopeForHoistingFuncDeclInEval(globalObject, scope, function->name());
1146                  RETURN_IF_EXCEPTION(throwScope, checkedReturn(throwScope.exception()));
1147                  if (resolvedScope.isUndefined())
1148                      return checkedReturn(throwSyntaxError(globalObject, throwScope, makeString("Can't create duplicate variable in eval: '", String(function->name().impl()), "'")));
1149                  PutPropertySlot slot(variableObject);
1150                  // We need create this variables because it will be used to emits code by bytecode generator
1151                  variableObject->methodTable(vm)->put(variableObject, globalObject, function->name(), jsUndefined(), slot);
1152                  RETURN_IF_EXCEPTION(throwScope, checkedReturn(throwScope.exception()));
1153              }
1154  
1155              for (unsigned i = 0; i < numFunctionHoistingCandidates; ++i) {
1156                  const Identifier& ident = unlinkedCodeBlock->functionHoistingCandidate(i);
1157                  JSValue resolvedScope = JSScope::resolveScopeForHoistingFuncDeclInEval(globalObject, scope, ident);
1158                  RETURN_IF_EXCEPTION(throwScope, checkedReturn(throwScope.exception()));
1159                  if (!resolvedScope.isUndefined()) {
1160                      bool hasProperty = variableObject->hasProperty(globalObject, ident);
1161                      RETURN_IF_EXCEPTION(throwScope, checkedReturn(throwScope.exception()));
1162                      if (!hasProperty) {
1163                          PutPropertySlot slot(variableObject);
1164                          variableObject->methodTable(vm)->put(variableObject, globalObject, ident, jsUndefined(), slot);
1165                          RETURN_IF_EXCEPTION(throwScope, checkedReturn(throwScope.exception()));
1166                      }
1167                  }
1168              }
1169          }
1170      }
1171  
1172      JSCallee* callee = nullptr;
1173      if (scope == globalObject->globalScope())
1174          callee = globalObject->globalCallee();
1175      else
1176          callee = JSCallee::create(vm, globalObject, scope);
1177  
1178      // Reload CodeBlock. It is possible that we replaced CodeBlock while setting up the environment.
1179      {
1180          Exception* compileError = nullptr;
1181          codeBlock = loadCodeBlock(compileError);
1182          EXCEPTION_ASSERT(throwScope.exception() == compileError);
1183          if (UNLIKELY(!!compileError))
1184              return checkedReturn(compileError);
1185          ASSERT(codeBlock->numParameters() == 1); // 1 parameter for 'this'.
1186      }
1187  
1188      RefPtr<JITCode> jitCode;
1189      ProtoCallFrame protoCallFrame;
1190      {
1191          DisallowGC disallowGC; // Ensure no GC happens. GC can replace CodeBlock in Executable.
1192          jitCode = eval->generatedJITCode();
1193          protoCallFrame.init(codeBlock, globalObject, callee, thisValue, 1);
1194      }
1195  
1196      // Execute the code:
1197      throwScope.release();
1198      ASSERT(jitCode == eval->generatedJITCode().ptr());
1199      JSValue result = jitCode->execute(&vm, &protoCallFrame);
1200  
1201      return checkedReturn(result);
1202  }
1203  
1204  JSValue Interpreter::executeModuleProgram(ModuleProgramExecutable* executable, JSGlobalObject* lexicalGlobalObject, JSModuleEnvironment* scope)
1205  {
1206      VM& vm = scope->vm();
1207      auto throwScope = DECLARE_THROW_SCOPE(vm);
1208  
1209      auto clobberizeValidator = makeScopeExit([&] {
1210          vm.didEnterVM = true;
1211      });
1212  
1213      ASSERT_UNUSED(lexicalGlobalObject, &vm == &lexicalGlobalObject->vm());
1214      throwScope.assertNoException();
1215      ASSERT(!vm.isCollectorBusyOnCurrentThread());
1216      RELEASE_ASSERT(vm.currentThreadIsHoldingAPILock());
1217      if (vm.isCollectorBusyOnCurrentThread())
1218          return jsNull();
1219  
1220      JSGlobalObject* globalObject = scope->globalObject(vm);
1221      VMEntryScope entryScope(vm, scope->globalObject(vm));
1222      if (UNLIKELY(!vm.isSafeToRecurseSoft()))
1223          return checkedReturn(throwStackOverflowError(globalObject, throwScope));
1224  
1225      constexpr auto trapsMask = VMTraps::interruptingTraps();
1226      if (UNLIKELY(vm.needTrapHandling(trapsMask))) {
1227          vm.handleTraps(globalObject, vm.topCallFrame, trapsMask);
1228          RETURN_IF_EXCEPTION(throwScope, throwScope.exception());
1229      }
1230  
1231      if (scope->structure(vm)->isUncacheableDictionary())
1232          scope->flattenDictionaryObject(vm);
1233  
1234      JSCallee* callee = JSCallee::create(vm, globalObject, scope);
1235      ModuleProgramCodeBlock* codeBlock;
1236      {
1237          CodeBlock* tempCodeBlock;
1238          Exception* compileError = executable->prepareForExecution<ModuleProgramExecutable>(vm, nullptr, scope, CodeForCall, tempCodeBlock);
1239          EXCEPTION_ASSERT(throwScope.exception() == compileError);
1240          if (UNLIKELY(!!compileError))
1241              return checkedReturn(compileError);
1242          codeBlock = jsCast<ModuleProgramCodeBlock*>(tempCodeBlock);
1243          ASSERT(codeBlock->numParameters() == 1); // 1 parameter for 'this'.
1244      }
1245  
1246      RefPtr<JITCode> jitCode;
1247      ProtoCallFrame protoCallFrame;
1248      {
1249          DisallowGC disallowGC; // Ensure no GC happens. GC can replace CodeBlock in Executable.
1250          jitCode = executable->generatedJITCode();
1251          // The |this| of the module is always `undefined`.
1252          // http://www.ecma-international.org/ecma-262/6.0/#sec-module-environment-records-hasthisbinding
1253          // http://www.ecma-international.org/ecma-262/6.0/#sec-module-environment-records-getthisbinding
1254          protoCallFrame.init(codeBlock, globalObject, callee, jsUndefined(), 1);
1255      }
1256  
1257      // Execute the code:
1258      throwScope.release();
1259      ASSERT(jitCode == executable->generatedJITCode().ptr());
1260      JSValue result = jitCode->execute(&vm, &protoCallFrame);
1261  
1262      return checkedReturn(result);
1263  }
1264  
1265  NEVER_INLINE void Interpreter::debug(CallFrame* callFrame, DebugHookType debugHookType)
1266  {
1267      VM& vm = callFrame->deprecatedVM();
1268      auto scope = DECLARE_CATCH_SCOPE(vm);
1269  
1270      if (UNLIKELY(Options::debuggerTriggersBreakpointException()) && debugHookType == DidReachDebuggerStatement)
1271          WTFBreakpointTrap();
1272  
1273      Debugger* debugger = callFrame->lexicalGlobalObject(vm)->debugger();
1274      if (!debugger)
1275          return;
1276  
1277      ASSERT(callFrame->codeBlock()->hasDebuggerRequests());
1278      scope.assertNoException();
1279  
1280      switch (debugHookType) {
1281          case DidEnterCallFrame:
1282              debugger->callEvent(callFrame);
1283              break;
1284          case WillLeaveCallFrame:
1285              debugger->returnEvent(callFrame);
1286              break;
1287          case WillExecuteStatement:
1288              debugger->atStatement(callFrame);
1289              break;
1290          case WillExecuteExpression:
1291              debugger->atExpression(callFrame);
1292              break;
1293          case WillExecuteProgram:
1294              debugger->willExecuteProgram(callFrame);
1295              break;
1296          case DidExecuteProgram:
1297              debugger->didExecuteProgram(callFrame);
1298              break;
1299          case DidReachDebuggerStatement:
1300              debugger->didReachDebuggerStatement(callFrame);
1301              break;
1302      }
1303      scope.assertNoException();
1304  }
1305  
1306  } // namespace JSC
1307  
1308  namespace WTF {
1309  
1310  void printInternal(PrintStream& out, JSC::DebugHookType type)
1311  {
1312      switch (type) {
1313      case JSC::WillExecuteProgram:
1314          out.print("WillExecuteProgram");
1315          return;
1316      case JSC::DidExecuteProgram:
1317          out.print("DidExecuteProgram");
1318          return;
1319      case JSC::DidEnterCallFrame:
1320          out.print("DidEnterCallFrame");
1321          return;
1322      case JSC::DidReachDebuggerStatement:
1323          out.print("DidReachDebuggerStatement");
1324          return;
1325      case JSC::WillLeaveCallFrame:
1326          out.print("WillLeaveCallFrame");
1327          return;
1328      case JSC::WillExecuteStatement:
1329          out.print("WillExecuteStatement");
1330          return;
1331      case JSC::WillExecuteExpression:
1332          out.print("WillExecuteExpression");
1333          return;
1334      }
1335  }
1336  
1337  } // namespace WTF