2017-08-12 16:48:01 +00:00
/*
2020-08-29 13:27:11 +00:00
* Copyright ( C ) 2009 - 2019 Apple Inc . All rights reserved .
2017-08-12 16:48:01 +00:00
*
* Redistribution and use in source and binary forms , with or without
* modification , are permitted provided that the following conditions
* are met :
* 1. Redistributions of source code must retain the above copyright
* notice , this list of conditions and the following disclaimer .
* 2. Redistributions in binary form must reproduce the above copyright
* notice , this list of conditions and the following disclaimer in the
* documentation and / or other materials provided with the distribution .
*
* THIS SOFTWARE IS PROVIDED BY APPLE INC . ` ` AS IS ' ' AND ANY
* EXPRESS OR IMPLIED WARRANTIES , INCLUDING , BUT NOT LIMITED TO , THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED . IN NO EVENT SHALL APPLE INC . OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT , INDIRECT , INCIDENTAL , SPECIAL ,
* EXEMPLARY , OR CONSEQUENTIAL DAMAGES ( INCLUDING , BUT NOT LIMITED TO ,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES ; LOSS OF USE , DATA , OR
* PROFITS ; OR BUSINESS INTERRUPTION ) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY , WHETHER IN CONTRACT , STRICT LIABILITY , OR TORT
* ( INCLUDING NEGLIGENCE OR OTHERWISE ) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE , EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE .
*/
# include "config.h"
# include "CodeBlock.h"
# include "Debugger.h"
# include "EvalCodeBlock.h"
# include "FunctionCodeBlock.h"
2020-08-29 13:27:11 +00:00
# include "GlobalExecutable.h"
# include "IsoCellSetInlines.h"
2017-08-12 16:48:01 +00:00
# include "JIT.h"
2022-10-23 02:55:20 +00:00
# include "JSCellInlines.h"
# include "JSGlobalObjectInlines.h"
# include "JSObjectInlines.h"
2020-08-29 13:27:11 +00:00
# include "JSTemplateObjectDescriptor.h"
2017-08-12 16:48:01 +00:00
# include "LLIntEntrypoint.h"
# include "ModuleProgramCodeBlock.h"
2022-10-23 02:55:20 +00:00
# include "ParserError.h"
2017-08-12 16:48:01 +00:00
# include "ProgramCodeBlock.h"
# include "VMInlines.h"
namespace JSC {
2018-01-03 05:16:05 +00:00
const ClassInfo ScriptExecutable : : s_info = { " ScriptExecutable " , & ExecutableBase : : s_info , nullptr , nullptr , CREATE_METHOD_TABLE ( ScriptExecutable ) } ;
2017-08-12 16:48:01 +00:00
2022-10-23 02:55:20 +00:00
ScriptExecutable : : ScriptExecutable ( Structure * structure , VM & vm , const SourceCode & source , bool isInStrictContext , DerivedContextType derivedContextType , bool isInArrowFunctionContext , bool isInsideOrdinaryFunction , EvalContextType evalContextType , Intrinsic intrinsic )
2020-08-29 13:27:11 +00:00
: ExecutableBase ( vm , structure )
, m_source ( source )
, m_intrinsic ( intrinsic )
2017-08-12 16:48:01 +00:00
, m_features ( isInStrictContext ? StrictModeFeature : 0 )
, m_hasCapturedVariables ( false )
, m_neverInline ( false )
, m_neverOptimize ( false )
, m_neverFTLOptimize ( false )
, m_isArrowFunctionContext ( isInArrowFunctionContext )
, m_canUseOSRExitFuzzing ( true )
2020-08-29 13:27:11 +00:00
, m_codeForGeneratorBodyWasGenerated ( false )
2022-10-23 02:55:20 +00:00
, m_isInsideOrdinaryFunction ( isInsideOrdinaryFunction )
2017-08-12 16:48:01 +00:00
, m_derivedContextType ( static_cast < unsigned > ( derivedContextType ) )
, m_evalContextType ( static_cast < unsigned > ( evalContextType ) )
{
}
void ScriptExecutable : : destroy ( JSCell * cell )
{
static_cast < ScriptExecutable * > ( cell ) - > ScriptExecutable : : ~ ScriptExecutable ( ) ;
}
2020-08-29 13:27:11 +00:00
void ScriptExecutable : : clearCode ( IsoCellSet & clearableCodeSet )
{
m_jitCodeForCall = nullptr ;
m_jitCodeForConstruct = nullptr ;
m_jitCodeForCallWithArityCheck = MacroAssemblerCodePtr < JSEntryPtrTag > ( ) ;
m_jitCodeForConstructWithArityCheck = MacroAssemblerCodePtr < JSEntryPtrTag > ( ) ;
switch ( type ( ) ) {
case FunctionExecutableType : {
FunctionExecutable * executable = static_cast < FunctionExecutable * > ( this ) ;
executable - > m_codeBlockForCall . clear ( ) ;
executable - > m_codeBlockForConstruct . clear ( ) ;
break ;
}
case EvalExecutableType : {
EvalExecutable * executable = static_cast < EvalExecutable * > ( this ) ;
executable - > m_evalCodeBlock . clear ( ) ;
executable - > m_unlinkedEvalCodeBlock . clear ( ) ;
break ;
}
case ProgramExecutableType : {
ProgramExecutable * executable = static_cast < ProgramExecutable * > ( this ) ;
executable - > m_programCodeBlock . clear ( ) ;
executable - > m_unlinkedProgramCodeBlock . clear ( ) ;
break ;
}
case ModuleProgramExecutableType : {
ModuleProgramExecutable * executable = static_cast < ModuleProgramExecutable * > ( this ) ;
executable - > m_moduleProgramCodeBlock . clear ( ) ;
executable - > m_unlinkedModuleProgramCodeBlock . clear ( ) ;
executable - > m_moduleEnvironmentSymbolTable . clear ( ) ;
break ;
}
default :
RELEASE_ASSERT_NOT_REACHED ( ) ;
break ;
}
ASSERT ( & VM : : SpaceAndSet : : setFor ( * subspace ( ) ) = = & clearableCodeSet ) ;
clearableCodeSet . remove ( this ) ;
}
2017-08-12 16:48:01 +00:00
void ScriptExecutable : : installCode ( CodeBlock * codeBlock )
{
2022-10-23 02:55:20 +00:00
installCode ( codeBlock - > vm ( ) , codeBlock , codeBlock - > codeType ( ) , codeBlock - > specializationKind ( ) ) ;
2017-08-12 16:48:01 +00:00
}
void ScriptExecutable : : installCode ( VM & vm , CodeBlock * genericCodeBlock , CodeType codeType , CodeSpecializationKind kind )
{
if ( genericCodeBlock )
CODEBLOCK_LOG_EVENT ( genericCodeBlock , " installCode " , ( ) ) ;
CodeBlock * oldCodeBlock = nullptr ;
switch ( codeType ) {
case GlobalCode : {
ProgramExecutable * executable = jsCast < ProgramExecutable * > ( this ) ;
ProgramCodeBlock * codeBlock = static_cast < ProgramCodeBlock * > ( genericCodeBlock ) ;
ASSERT ( kind = = CodeForCall ) ;
2020-08-29 13:27:11 +00:00
oldCodeBlock = ExecutableToCodeBlockEdge : : deactivateAndUnwrap ( executable - > m_programCodeBlock . get ( ) ) ;
executable - > m_programCodeBlock . setMayBeNull ( vm , this , ExecutableToCodeBlockEdge : : wrapAndActivate ( codeBlock ) ) ;
2017-08-12 16:48:01 +00:00
break ;
}
case ModuleCode : {
ModuleProgramExecutable * executable = jsCast < ModuleProgramExecutable * > ( this ) ;
ModuleProgramCodeBlock * codeBlock = static_cast < ModuleProgramCodeBlock * > ( genericCodeBlock ) ;
ASSERT ( kind = = CodeForCall ) ;
2020-08-29 13:27:11 +00:00
oldCodeBlock = ExecutableToCodeBlockEdge : : deactivateAndUnwrap ( executable - > m_moduleProgramCodeBlock . get ( ) ) ;
executable - > m_moduleProgramCodeBlock . setMayBeNull ( vm , this , ExecutableToCodeBlockEdge : : wrapAndActivate ( codeBlock ) ) ;
2017-08-12 16:48:01 +00:00
break ;
}
case EvalCode : {
EvalExecutable * executable = jsCast < EvalExecutable * > ( this ) ;
EvalCodeBlock * codeBlock = static_cast < EvalCodeBlock * > ( genericCodeBlock ) ;
ASSERT ( kind = = CodeForCall ) ;
2020-08-29 13:27:11 +00:00
oldCodeBlock = ExecutableToCodeBlockEdge : : deactivateAndUnwrap ( executable - > m_evalCodeBlock . get ( ) ) ;
executable - > m_evalCodeBlock . setMayBeNull ( vm , this , ExecutableToCodeBlockEdge : : wrapAndActivate ( codeBlock ) ) ;
2017-08-12 16:48:01 +00:00
break ;
}
case FunctionCode : {
FunctionExecutable * executable = jsCast < FunctionExecutable * > ( this ) ;
FunctionCodeBlock * codeBlock = static_cast < FunctionCodeBlock * > ( genericCodeBlock ) ;
switch ( kind ) {
case CodeForCall :
2020-08-29 13:27:11 +00:00
oldCodeBlock = ExecutableToCodeBlockEdge : : deactivateAndUnwrap ( executable - > m_codeBlockForCall . get ( ) ) ;
executable - > m_codeBlockForCall . setMayBeNull ( vm , this , ExecutableToCodeBlockEdge : : wrapAndActivate ( codeBlock ) ) ;
2017-08-12 16:48:01 +00:00
break ;
case CodeForConstruct :
2020-08-29 13:27:11 +00:00
oldCodeBlock = ExecutableToCodeBlockEdge : : deactivateAndUnwrap ( executable - > m_codeBlockForConstruct . get ( ) ) ;
executable - > m_codeBlockForConstruct . setMayBeNull ( vm , this , ExecutableToCodeBlockEdge : : wrapAndActivate ( codeBlock ) ) ;
2017-08-12 16:48:01 +00:00
break ;
}
break ;
}
}
switch ( kind ) {
case CodeForCall :
m_jitCodeForCall = genericCodeBlock ? genericCodeBlock - > jitCode ( ) : nullptr ;
2020-08-29 13:27:11 +00:00
m_jitCodeForCallWithArityCheck = nullptr ;
2017-08-12 16:48:01 +00:00
break ;
case CodeForConstruct :
m_jitCodeForConstruct = genericCodeBlock ? genericCodeBlock - > jitCode ( ) : nullptr ;
2020-08-29 13:27:11 +00:00
m_jitCodeForConstructWithArityCheck = nullptr ;
2017-08-12 16:48:01 +00:00
break ;
}
2020-08-29 13:27:11 +00:00
auto & clearableCodeSet = VM : : SpaceAndSet : : setFor ( * subspace ( ) ) ;
if ( hasClearableCode ( vm ) )
clearableCodeSet . add ( this ) ;
else
clearableCodeSet . remove ( this ) ;
2017-08-12 16:48:01 +00:00
if ( genericCodeBlock ) {
RELEASE_ASSERT ( genericCodeBlock - > ownerExecutable ( ) = = this ) ;
RELEASE_ASSERT ( JITCode : : isExecutableScript ( genericCodeBlock - > jitType ( ) ) ) ;
2022-10-23 02:55:20 +00:00
dataLogLnIf ( Options : : verboseOSR ( ) , " Installing " , * genericCodeBlock ) ;
2017-08-12 16:48:01 +00:00
2020-08-29 13:27:11 +00:00
if ( UNLIKELY ( vm . m_perBytecodeProfiler ) )
2017-08-12 16:48:01 +00:00
vm . m_perBytecodeProfiler - > ensureBytecodesFor ( genericCodeBlock ) ;
2020-08-29 13:27:11 +00:00
Debugger * debugger = genericCodeBlock - > globalObject ( ) - > debugger ( ) ;
if ( UNLIKELY ( debugger ) )
2017-08-12 16:48:01 +00:00
debugger - > registerCodeBlock ( genericCodeBlock ) ;
}
if ( oldCodeBlock )
oldCodeBlock - > unlinkIncomingCalls ( ) ;
vm . heap . writeBarrier ( this ) ;
}
2020-08-29 13:27:11 +00:00
bool ScriptExecutable : : hasClearableCode ( VM & vm ) const
{
if ( m_jitCodeForCall
| | m_jitCodeForConstruct
| | m_jitCodeForCallWithArityCheck
| | m_jitCodeForConstructWithArityCheck )
return true ;
if ( structure ( vm ) - > classInfo ( ) = = FunctionExecutable : : info ( ) ) {
auto * executable = static_cast < const FunctionExecutable * > ( this ) ;
if ( executable - > m_codeBlockForCall | | executable - > m_codeBlockForConstruct )
return true ;
} else if ( structure ( vm ) - > classInfo ( ) = = EvalExecutable : : info ( ) ) {
auto * executable = static_cast < const EvalExecutable * > ( this ) ;
if ( executable - > m_evalCodeBlock | | executable - > m_unlinkedEvalCodeBlock )
return true ;
} else if ( structure ( vm ) - > classInfo ( ) = = ProgramExecutable : : info ( ) ) {
auto * executable = static_cast < const ProgramExecutable * > ( this ) ;
if ( executable - > m_programCodeBlock | | executable - > m_unlinkedProgramCodeBlock )
return true ;
} else if ( structure ( vm ) - > classInfo ( ) = = ModuleProgramExecutable : : info ( ) ) {
auto * executable = static_cast < const ModuleProgramExecutable * > ( this ) ;
if ( executable - > m_moduleProgramCodeBlock
| | executable - > m_unlinkedModuleProgramCodeBlock
| | executable - > m_moduleEnvironmentSymbolTable )
return true ;
}
return false ;
}
2017-08-12 16:48:01 +00:00
CodeBlock * ScriptExecutable : : newCodeBlockFor (
2020-08-29 13:27:11 +00:00
CodeSpecializationKind kind , JSFunction * function , JSScope * scope , Exception * & exception )
2017-08-12 16:48:01 +00:00
{
2022-10-23 02:55:20 +00:00
VM & vm = scope - > vm ( ) ;
auto throwScope = DECLARE_THROW_SCOPE ( vm ) ;
2017-08-12 16:48:01 +00:00
2022-10-23 02:55:20 +00:00
ASSERT ( vm . heap . isDeferred ( ) ) ;
2017-08-12 16:48:01 +00:00
ASSERT ( endColumn ( ) ! = UINT_MAX ) ;
2022-10-23 02:55:20 +00:00
JSGlobalObject * globalObject = scope - > globalObject ( vm ) ;
2018-01-03 05:16:05 +00:00
2022-10-23 02:55:20 +00:00
if ( classInfo ( vm ) = = EvalExecutable : : info ( ) ) {
2017-08-12 16:48:01 +00:00
EvalExecutable * executable = jsCast < EvalExecutable * > ( this ) ;
RELEASE_ASSERT ( kind = = CodeForCall ) ;
RELEASE_ASSERT ( ! executable - > m_evalCodeBlock ) ;
RELEASE_ASSERT ( ! function ) ;
2022-10-23 02:55:20 +00:00
auto * codeBlock = EvalCodeBlock : : create ( vm ,
2020-08-29 13:27:11 +00:00
executable , executable - > m_unlinkedEvalCodeBlock . get ( ) , scope ) ;
EXCEPTION_ASSERT ( throwScope . exception ( ) | | codeBlock ) ;
2018-01-03 05:16:05 +00:00
if ( ! codeBlock ) {
exception = throwException (
2022-10-23 02:55:20 +00:00
globalObject , throwScope ,
createOutOfMemoryError ( globalObject ) ) ;
2018-01-03 05:16:05 +00:00
return nullptr ;
}
return codeBlock ;
2017-08-12 16:48:01 +00:00
}
2022-10-23 02:55:20 +00:00
if ( classInfo ( vm ) = = ProgramExecutable : : info ( ) ) {
2017-08-12 16:48:01 +00:00
ProgramExecutable * executable = jsCast < ProgramExecutable * > ( this ) ;
RELEASE_ASSERT ( kind = = CodeForCall ) ;
RELEASE_ASSERT ( ! executable - > m_programCodeBlock ) ;
RELEASE_ASSERT ( ! function ) ;
2022-10-23 02:55:20 +00:00
auto * codeBlock = ProgramCodeBlock : : create ( vm ,
2020-08-29 13:27:11 +00:00
executable , executable - > m_unlinkedProgramCodeBlock . get ( ) , scope ) ;
EXCEPTION_ASSERT ( throwScope . exception ( ) | | codeBlock ) ;
2018-01-03 05:16:05 +00:00
if ( ! codeBlock ) {
exception = throwException (
2022-10-23 02:55:20 +00:00
globalObject , throwScope ,
createOutOfMemoryError ( globalObject ) ) ;
2018-01-03 05:16:05 +00:00
return nullptr ;
}
return codeBlock ;
2017-08-12 16:48:01 +00:00
}
2022-10-23 02:55:20 +00:00
if ( classInfo ( vm ) = = ModuleProgramExecutable : : info ( ) ) {
2017-08-12 16:48:01 +00:00
ModuleProgramExecutable * executable = jsCast < ModuleProgramExecutable * > ( this ) ;
RELEASE_ASSERT ( kind = = CodeForCall ) ;
RELEASE_ASSERT ( ! executable - > m_moduleProgramCodeBlock ) ;
RELEASE_ASSERT ( ! function ) ;
2022-10-23 02:55:20 +00:00
auto * codeBlock = ModuleProgramCodeBlock : : create ( vm ,
2020-08-29 13:27:11 +00:00
executable , executable - > m_unlinkedModuleProgramCodeBlock . get ( ) , scope ) ;
EXCEPTION_ASSERT ( throwScope . exception ( ) | | codeBlock ) ;
2018-01-03 05:16:05 +00:00
if ( ! codeBlock ) {
exception = throwException (
2022-10-23 02:55:20 +00:00
globalObject , throwScope ,
createOutOfMemoryError ( globalObject ) ) ;
2018-01-03 05:16:05 +00:00
return nullptr ;
}
return codeBlock ;
2017-08-12 16:48:01 +00:00
}
2022-10-23 02:55:20 +00:00
RELEASE_ASSERT ( classInfo ( vm ) = = FunctionExecutable : : info ( ) ) ;
2017-08-12 16:48:01 +00:00
RELEASE_ASSERT ( function ) ;
FunctionExecutable * executable = jsCast < FunctionExecutable * > ( this ) ;
RELEASE_ASSERT ( ! executable - > codeBlockFor ( kind ) ) ;
ParserError error ;
2020-08-29 13:27:11 +00:00
OptionSet < CodeGenerationMode > codeGenerationMode = globalObject - > defaultCodeGenerationMode ( ) ;
// We continue using the same CodeGenerationMode for Generators because live generator objects can
// keep the state which is only valid with the CodeBlock compiled with the same CodeGenerationMode.
if ( isGeneratorOrAsyncFunctionBodyParseMode ( executable - > parseMode ( ) ) ) {
if ( ! m_codeForGeneratorBodyWasGenerated ) {
m_codeGenerationModeForGeneratorBody = codeGenerationMode ;
m_codeForGeneratorBodyWasGenerated = true ;
} else
codeGenerationMode = m_codeGenerationModeForGeneratorBody ;
}
2017-08-12 16:48:01 +00:00
UnlinkedFunctionCodeBlock * unlinkedCodeBlock =
executable - > m_unlinkedExecutable - > unlinkedCodeBlockFor (
2022-10-23 02:55:20 +00:00
vm , executable - > source ( ) , kind , codeGenerationMode , error ,
2017-08-12 16:48:01 +00:00
executable - > parseMode ( ) ) ;
recordParse (
executable - > m_unlinkedExecutable - > features ( ) ,
executable - > m_unlinkedExecutable - > hasCapturedVariables ( ) ,
lastLine ( ) , endColumn ( ) ) ;
if ( ! unlinkedCodeBlock ) {
exception = throwException (
2022-10-23 02:55:20 +00:00
globalObject , throwScope ,
2020-08-29 13:27:11 +00:00
error . toErrorObject ( globalObject , executable - > source ( ) ) ) ;
2017-08-12 16:48:01 +00:00
return nullptr ;
}
2022-10-23 02:55:20 +00:00
auto * codeBlock = FunctionCodeBlock : : create ( vm , executable , unlinkedCodeBlock , scope ) ;
if ( throwScope . exception ( ) )
exception = throwScope . exception ( ) ;
return codeBlock ;
2017-08-12 16:48:01 +00:00
}
CodeBlock * ScriptExecutable : : newReplacementCodeBlockFor (
CodeSpecializationKind kind )
{
2022-10-23 02:55:20 +00:00
VM & vm = this - > vm ( ) ;
2018-01-03 05:16:05 +00:00
if ( classInfo ( vm ) = = EvalExecutable : : info ( ) ) {
2017-08-12 16:48:01 +00:00
RELEASE_ASSERT ( kind = = CodeForCall ) ;
EvalExecutable * executable = jsCast < EvalExecutable * > ( this ) ;
EvalCodeBlock * baseline = static_cast < EvalCodeBlock * > (
2020-08-29 13:27:11 +00:00
executable - > codeBlock ( ) - > baselineVersion ( ) ) ;
2022-10-23 02:55:20 +00:00
EvalCodeBlock * result = EvalCodeBlock : : create ( vm ,
2017-08-12 16:48:01 +00:00
CodeBlock : : CopyParsedBlock , * baseline ) ;
2018-01-03 05:16:05 +00:00
result - > setAlternative ( vm , baseline ) ;
2017-08-12 16:48:01 +00:00
return result ;
}
2018-01-03 05:16:05 +00:00
if ( classInfo ( vm ) = = ProgramExecutable : : info ( ) ) {
2017-08-12 16:48:01 +00:00
RELEASE_ASSERT ( kind = = CodeForCall ) ;
ProgramExecutable * executable = jsCast < ProgramExecutable * > ( this ) ;
ProgramCodeBlock * baseline = static_cast < ProgramCodeBlock * > (
2020-08-29 13:27:11 +00:00
executable - > codeBlock ( ) - > baselineVersion ( ) ) ;
2022-10-23 02:55:20 +00:00
ProgramCodeBlock * result = ProgramCodeBlock : : create ( vm ,
2017-08-12 16:48:01 +00:00
CodeBlock : : CopyParsedBlock , * baseline ) ;
2018-01-03 05:16:05 +00:00
result - > setAlternative ( vm , baseline ) ;
2017-08-12 16:48:01 +00:00
return result ;
}
2018-01-03 05:16:05 +00:00
if ( classInfo ( vm ) = = ModuleProgramExecutable : : info ( ) ) {
2017-08-12 16:48:01 +00:00
RELEASE_ASSERT ( kind = = CodeForCall ) ;
ModuleProgramExecutable * executable = jsCast < ModuleProgramExecutable * > ( this ) ;
ModuleProgramCodeBlock * baseline = static_cast < ModuleProgramCodeBlock * > (
2020-08-29 13:27:11 +00:00
executable - > codeBlock ( ) - > baselineVersion ( ) ) ;
2022-10-23 02:55:20 +00:00
ModuleProgramCodeBlock * result = ModuleProgramCodeBlock : : create ( vm ,
2017-08-12 16:48:01 +00:00
CodeBlock : : CopyParsedBlock , * baseline ) ;
2018-01-03 05:16:05 +00:00
result - > setAlternative ( vm , baseline ) ;
2017-08-12 16:48:01 +00:00
return result ;
}
2018-01-03 05:16:05 +00:00
RELEASE_ASSERT ( classInfo ( vm ) = = FunctionExecutable : : info ( ) ) ;
2017-08-12 16:48:01 +00:00
FunctionExecutable * executable = jsCast < FunctionExecutable * > ( this ) ;
FunctionCodeBlock * baseline = static_cast < FunctionCodeBlock * > (
executable - > codeBlockFor ( kind ) - > baselineVersion ( ) ) ;
2022-10-23 02:55:20 +00:00
FunctionCodeBlock * result = FunctionCodeBlock : : create ( vm ,
2017-08-12 16:48:01 +00:00
CodeBlock : : CopyParsedBlock , * baseline ) ;
2018-01-03 05:16:05 +00:00
result - > setAlternative ( vm , baseline ) ;
2017-08-12 16:48:01 +00:00
return result ;
}
2020-08-29 13:27:11 +00:00
static void setupLLInt ( CodeBlock * codeBlock )
2017-08-12 16:48:01 +00:00
{
2020-08-29 13:27:11 +00:00
LLInt : : setEntrypoint ( codeBlock ) ;
2017-08-12 16:48:01 +00:00
}
static void setupJIT ( VM & vm , CodeBlock * codeBlock )
{
# if ENABLE(JIT)
2022-10-23 02:55:20 +00:00
CompilationResult result = JIT : : compile ( vm , codeBlock , JITCompilationMustSucceed ) ;
2017-08-12 16:48:01 +00:00
RELEASE_ASSERT ( result = = CompilationSuccessful ) ;
# else
UNUSED_PARAM ( vm ) ;
UNUSED_PARAM ( codeBlock ) ;
UNREACHABLE_FOR_PLATFORM ( ) ;
# endif
}
2020-08-29 13:27:11 +00:00
Exception * ScriptExecutable : : prepareForExecutionImpl (
2017-08-12 16:48:01 +00:00
VM & vm , JSFunction * function , JSScope * scope , CodeSpecializationKind kind , CodeBlock * & resultCodeBlock )
{
auto throwScope = DECLARE_THROW_SCOPE ( vm ) ;
DeferGCForAWhile deferGC ( vm . heap ) ;
2020-08-29 13:27:11 +00:00
if ( UNLIKELY ( vm . getAndClearFailNextNewCodeBlock ( ) ) ) {
2022-10-23 02:55:20 +00:00
JSGlobalObject * globalObject = scope - > globalObject ( vm ) ;
return throwException ( globalObject , throwScope , createError ( globalObject , " Forced Failure " _s ) ) ;
2017-08-12 16:48:01 +00:00
}
2020-08-29 13:27:11 +00:00
Exception * exception = nullptr ;
2017-08-12 16:48:01 +00:00
CodeBlock * codeBlock = newCodeBlockFor ( kind , function , scope , exception ) ;
resultCodeBlock = codeBlock ;
2020-08-29 13:27:11 +00:00
EXCEPTION_ASSERT ( ! ! throwScope . exception ( ) = = ! codeBlock ) ;
2017-08-12 16:48:01 +00:00
if ( UNLIKELY ( ! codeBlock ) )
return exception ;
if ( Options : : validateBytecode ( ) )
codeBlock - > validate ( ) ;
if ( Options : : useLLInt ( ) )
2020-08-29 13:27:11 +00:00
setupLLInt ( codeBlock ) ;
2017-08-12 16:48:01 +00:00
else
setupJIT ( vm , codeBlock ) ;
installCode ( vm , codeBlock , codeBlock - > codeType ( ) , codeBlock - > specializationKind ( ) ) ;
return nullptr ;
}
2020-08-29 13:27:11 +00:00
ScriptExecutable * ScriptExecutable : : topLevelExecutable ( )
{
switch ( type ( ) ) {
case FunctionExecutableType :
return jsCast < FunctionExecutable * > ( this ) - > topLevelExecutable ( ) ;
default :
return this ;
}
}
2022-10-23 02:55:20 +00:00
JSArray * ScriptExecutable : : createTemplateObject ( JSGlobalObject * globalObject , JSTemplateObjectDescriptor * descriptor )
2020-08-29 13:27:11 +00:00
{
2022-10-23 02:55:20 +00:00
VM & vm = globalObject - > vm ( ) ;
2020-08-29 13:27:11 +00:00
auto scope = DECLARE_THROW_SCOPE ( vm ) ;
TemplateObjectMap & templateObjectMap = ensureTemplateObjectMap ( vm ) ;
TemplateObjectMap : : AddResult result ;
{
auto locker = holdLock ( cellLock ( ) ) ;
result = templateObjectMap . add ( descriptor - > endOffset ( ) , WriteBarrier < JSArray > ( ) ) ;
}
if ( JSArray * array = result . iterator - > value . get ( ) )
return array ;
2022-10-23 02:55:20 +00:00
JSArray * templateObject = descriptor - > createTemplateObject ( globalObject ) ;
2020-08-29 13:27:11 +00:00
RETURN_IF_EXCEPTION ( scope , nullptr ) ;
result . iterator - > value . set ( vm , this , templateObject ) ;
return templateObject ;
}
auto ScriptExecutable : : ensureTemplateObjectMapImpl ( std : : unique_ptr < TemplateObjectMap > & dest ) - > TemplateObjectMap &
{
if ( dest )
return * dest ;
2022-10-23 02:55:20 +00:00
auto result = makeUnique < TemplateObjectMap > ( ) ;
2020-08-29 13:27:11 +00:00
WTF : : storeStoreFence ( ) ;
dest = WTFMove ( result ) ;
return * dest ;
}
auto ScriptExecutable : : ensureTemplateObjectMap ( VM & vm ) - > TemplateObjectMap &
{
switch ( type ( ) ) {
case FunctionExecutableType :
return static_cast < FunctionExecutable * > ( this ) - > ensureTemplateObjectMap ( vm ) ;
case EvalExecutableType :
return static_cast < EvalExecutable * > ( this ) - > ensureTemplateObjectMap ( vm ) ;
case ProgramExecutableType :
return static_cast < ProgramExecutable * > ( this ) - > ensureTemplateObjectMap ( vm ) ;
case ModuleProgramExecutableType :
default :
ASSERT ( type ( ) = = ModuleProgramExecutableType ) ;
return static_cast < ModuleProgramExecutable * > ( this ) - > ensureTemplateObjectMap ( vm ) ;
}
}
2017-08-12 16:48:01 +00:00
CodeBlockHash ScriptExecutable : : hashFor ( CodeSpecializationKind kind ) const
{
return CodeBlockHash ( source ( ) , kind ) ;
}
2020-08-29 13:27:11 +00:00
Optional < int > ScriptExecutable : : overrideLineNumber ( VM & vm ) const
{
if ( inherits < FunctionExecutable > ( vm ) )
return jsCast < const FunctionExecutable * > ( this ) - > overrideLineNumber ( ) ;
return WTF : : nullopt ;
}
unsigned ScriptExecutable : : typeProfilingStartOffset ( VM & vm ) const
{
if ( inherits < FunctionExecutable > ( vm ) )
return jsCast < const FunctionExecutable * > ( this ) - > typeProfilingStartOffset ( vm ) ;
if ( inherits < EvalExecutable > ( vm ) )
return UINT_MAX ;
return 0 ;
}
unsigned ScriptExecutable : : typeProfilingEndOffset ( VM & vm ) const
{
if ( inherits < FunctionExecutable > ( vm ) )
return jsCast < const FunctionExecutable * > ( this ) - > typeProfilingEndOffset ( vm ) ;
if ( inherits < EvalExecutable > ( vm ) )
return UINT_MAX ;
return source ( ) . length ( ) - 1 ;
}
void ScriptExecutable : : recordParse ( CodeFeatures features , bool hasCapturedVariables , int lastLine , unsigned endColumn )
{
switch ( type ( ) ) {
case FunctionExecutableType :
// Since UnlinkedFunctionExecutable holds the information to calculate lastLine and endColumn, we do not need to remember them in ScriptExecutable's fields.
jsCast < FunctionExecutable * > ( this ) - > recordParse ( features , hasCapturedVariables ) ;
return ;
default :
jsCast < GlobalExecutable * > ( this ) - > recordParse ( features , hasCapturedVariables , lastLine , endColumn ) ;
return ;
}
}
int ScriptExecutable : : lastLine ( ) const
{
switch ( type ( ) ) {
case FunctionExecutableType :
return jsCast < const FunctionExecutable * > ( this ) - > lastLine ( ) ;
default :
return jsCast < const GlobalExecutable * > ( this ) - > lastLine ( ) ;
}
return 0 ;
}
unsigned ScriptExecutable : : endColumn ( ) const
{
switch ( type ( ) ) {
case FunctionExecutableType :
return jsCast < const FunctionExecutable * > ( this ) - > endColumn ( ) ;
default :
return jsCast < const GlobalExecutable * > ( this ) - > endColumn ( ) ;
}
return 0 ;
}
2017-08-12 16:48:01 +00:00
} // namespace JSC