Ignore:
Timestamp:
Nov 22, 2021, 4:14:28 AM (3 years ago)
Author:
[email protected]
Message:

[JSC] Make sharing of unlinked baseline code possible on JSVALUE32_64
https://bugs.webkit.org/show_bug.cgi?id=232624

Patch by Geza Lore <Geza Lore> on 2021-11-22
Reviewed by Yusuke Suzuki.

PerformanceTests/SunSpider:

Add extra SunSpider run on 32-bit platforms exerciseing baseline JIT
code sharing.

  • with-baseline-code-sharing.yaml: Added.

Source/JavaScriptCore:

This patch contains a few different changes, which taken together make
it possible to share the unlinked baseline JIT code between different
CodeBlocks on JSVALUE32_64 platforms. Note that by default, code
sharing is disabled on JSVALUE32_64 due to the increased executable
memory usage it may cause. The reson the executable memory usage might
increase is that the UnlinkedCodeBlock has a longer lifetime than the
corresponding linked CodeBlocks (due to the CodeCache I'm told), and
when using code sharing, it holds a reference to the JITed code. This
then prevents recycling of executable memory while the
UnlinkedCodeBlock is live, while without sharing we could have
reclaimed some of the executable memory earlier.

The high level changes in this pach are:

  1. A lot of baseline implementations of the opcodes that needed

changing for the unlinked baseline are now unified between the
JSVALUE64 and JSVALUE32_64 platforms. Note that while this required
adding some abstraction, the code generated by the baseline JIT on
JSVALUE64 should be identical using this abstraction compared to
before.

  1. I added a JSRInfo class which defines standard names for certain

JSValueReg instances. This enables a lot of the unification in the
point above to be expressed in a very simple manner, with very little
transformation of the existing code. Again, this should have no impact
on the generated code on JSVALUE64, apart from some register
substitutions.

  1. The sizes of the resolve_scope and get_from_scope ops increased

significantly with the unlinked baseline. This can cause issues on
some JSVALUE32_64 targets where memory is more precious, so for these
two ops I swapped in the implementations under EXTRA_CTI_THUNKS, which
implement these using shared stubs. These stubs work on all platforms
that support ENABLE(JIT), so they are now the only implementation and
I have removed the basic bloated versions.

  1. Removed some unused code and fields I discovered while working on

this, strictly speaking this is not necessary for the functional
change.

  • JavaScriptCore.xcodeproj/project.pbxproj:
  • Sources.txt:
  • jit/AssemblyHelpers.h:

(JSC::AssemblyHelpers::storeValue):
(JSC::AssemblyHelpers::isNull):
(JSC::AssemblyHelpers::isNotNull):
(JSC::AssemblyHelpers::emitTurnUndefinedIntoNull):
(JSC::AssemblyHelpers::noOverlap):
(JSC::AssemblyHelpers::noOverlapImpl):
(JSC::AssemblyHelpers::noOverlapImplRegMask):

  • jit/GPRInfo.h:
  • jit/JIT.cpp:

(JSC::JIT::privateCompileSlowCases):
(JSC::JIT::compileAndLinkWithoutFinalizing):
(JSC::JIT::link):
(JSC::JIT::privateCompileExceptionHandlers):

  • jit/JIT.h:
  • jit/JITArithmetic.cpp:

(JSC::JIT::emit_compareAndJumpImpl):
(JSC::JIT::emit_compareUnsignedAndJumpImpl):
(JSC::JIT::emit_compareUnsignedImpl):
(JSC::JIT::emit_op_mod):
(JSC::JIT::emit_compareAndJump):
(JSC::JIT::emit_compareUnsignedAndJump):
(JSC::JIT::emit_compareUnsigned):
(JSC::JIT::emit_compareAndJumpSlow):
(JSC::JIT::emitBinaryDoubleOp):

  • jit/JITArithmetic32_64.cpp:

(JSC::JIT::emit_op_unsigned):
(JSC::JIT::emit_op_inc):
(JSC::JIT::emit_op_dec):

  • jit/JITCall.cpp:

(JSC::JIT::emit_op_ret):
(JSC::JIT::compileSetupFrame):
(JSC::JIT::compileOpCall):
(JSC::JIT::emit_op_iterator_open):
(JSC::JIT::emit_op_iterator_next):

  • jit/JITInlines.h:

(JSC::JIT::getConstantOperand):
(JSC::JIT::appendCallWithExceptionCheckSetJSValueResult):
(JSC::JIT::appendCallWithExceptionCheckSetJSValueResultWithProfile):
(JSC::JIT::emitValueProfilingSiteIfProfiledOpcode):
(JSC::JIT::emitValueProfilingSite):
(JSC::JIT::emitGetVirtualRegister):
(JSC::JIT::emitPutVirtualRegister):
(JSC::JIT::emitGetVirtualRegisterPayload):
(JSC::JIT::emitGetVirtualRegisterTag):
(JSC::JIT::emitLoadDouble):
(JSC::loadAddrOfCodeBlockConstantBuffer):
(JSC::JIT::loadCodeBlockConstant):
(JSC::JIT::loadCodeBlockConstantPayload):
(JSC::JIT::loadCodeBlockConstantTag):

  • jit/JITOpcodes.cpp:

(JSC::JIT::emit_op_mov):
(JSC::JIT::emit_op_end):
(JSC::JIT::emit_op_new_object):
(JSC::JIT::emitSlow_op_new_object):
(JSC::JIT::emit_op_typeof_is_undefined):
(JSC::JIT::emit_op_is_undefined_or_null):
(JSC::JIT::emit_op_set_function_name):
(JSC::JIT::emit_op_jfalse):
(JSC::JIT::valueIsFalseyGenerator):
(JSC::JIT::emit_op_jeq_null):
(JSC::JIT::emit_op_jneq_null):
(JSC::JIT::emit_op_jeq_ptr):
(JSC::JIT::emit_op_jneq_ptr):
(JSC::JIT::emit_op_eq):
(JSC::JIT::emit_op_jeq):
(JSC::JIT::emit_op_jtrue):
(JSC::JIT::valueIsTruthyGenerator):
(JSC::JIT::emit_op_neq):
(JSC::JIT::emit_op_jneq):
(JSC::JIT::emit_op_throw):
(JSC::JIT::compileOpStrictEq):
(JSC::JIT::compileOpStrictEqJump):
(JSC::JIT::emit_op_switch_imm):
(JSC::JIT::emit_op_switch_char):
(JSC::JIT::emit_op_switch_string):
(JSC::JIT::emit_op_eq_null):
(JSC::JIT::emit_op_neq_null):
(JSC::JIT::emit_op_to_this):
(JSC::JIT::emit_op_create_this):
(JSC::JIT::emit_op_instanceof_custom):
(JSC::JIT::emitSlow_op_instanceof_custom):
(JSC::JIT::emit_op_loop_hint):
(JSC::JIT::emitNewFuncCommon):
(JSC::JIT::emitNewFuncExprCommon):
(JSC::JIT::emit_op_new_array_with_size):
(JSC::JIT::emit_op_profile_type):
(JSC::JIT::emit_op_log_shadow_chicken_prologue):
(JSC::JIT::emit_op_log_shadow_chicken_tail):
(JSC::JIT::emit_op_get_argument):
(JSC::JIT::emit_op_get_prototype_of):

  • jit/JITOpcodes32_64.cpp:

(JSC::JIT::emit_op_overrides_has_instance):
(JSC::JIT::emit_op_instanceof):
(JSC::JIT::emitSlow_op_instanceof):
(JSC::JIT::emit_op_is_empty):
(JSC::JIT::emit_op_is_boolean):
(JSC::JIT::emit_op_is_number):
(JSC::JIT::emit_op_is_cell_with_type):
(JSC::JIT::emit_op_is_object):
(JSC::JIT::emit_op_to_primitive):
(JSC::JIT::emit_op_to_property_key):
(JSC::JIT::emit_op_not):
(JSC::JIT::emit_op_jundefined_or_null):
(JSC::JIT::emit_op_jnundefined_or_null):
(JSC::JIT::emit_op_jeq_ptr):
(JSC::JIT::emit_op_jneq_ptr):
(JSC::JIT::emit_op_eq):
(JSC::JIT::emitSlow_op_eq):
(JSC::JIT::emit_op_jeq):
(JSC::JIT::compileOpEqJumpSlow):
(JSC::JIT::emit_op_neq):
(JSC::JIT::emitSlow_op_neq):
(JSC::JIT::emit_op_jneq):
(JSC::JIT::compileOpStrictEq):
(JSC::JIT::compileOpStrictEqJump):
(JSC::JIT::emitSlow_op_jstricteq):
(JSC::JIT::emitSlow_op_jnstricteq):
(JSC::JIT::emit_op_to_number):
(JSC::JIT::emit_op_to_numeric):
(JSC::JIT::emit_op_to_string):
(JSC::JIT::emit_op_to_object):
(JSC::JIT::emit_op_get_parent_scope):
(JSC::JIT::emit_op_enter):
(JSC::JIT::emit_op_check_tdz):

  • jit/JITPropertyAccess.cpp:

(JSC::JIT::emit_op_put_getter_by_id):
(JSC::JIT::emit_op_put_setter_by_id):
(JSC::JIT::emit_op_put_getter_setter_by_id):
(JSC::JIT::emit_op_put_getter_by_val):
(JSC::JIT::emit_op_put_setter_by_val):
(JSC::JIT::emit_op_resolve_scope):
(JSC::JIT::generateOpResolveScopeThunk):
(JSC::JIT::slow_op_resolve_scopeGenerator):
(JSC::JIT::emit_op_get_from_scope):
(JSC::JIT::generateOpGetFromScopeThunk):
(JSC::JIT::slow_op_get_from_scopeGenerator):
(JSC::JIT::emit_op_put_to_scope):
(JSC::JIT::emit_op_get_from_arguments):
(JSC::JIT::emit_op_put_to_arguments):
(JSC::JIT::emit_op_get_internal_field):
(JSC::JIT::emit_op_put_internal_field):
(JSC::JIT::emit_op_get_property_enumerator):
(JSC::JIT::emit_op_enumerator_next):
(JSC::JIT::emit_op_enumerator_get_by_val):
(JSC::JIT::emitSlow_op_enumerator_get_by_val):
(JSC::JIT::emit_op_enumerator_in_by_val):
(JSC::JIT::emit_op_enumerator_has_own_property):
(JSC::JIT::emitWriteBarrier):

  • jit/JITPropertyAccess32_64.cpp: Removed.
  • jit/JSInterfaceJIT.h:
  • jit/ThunkGenerators.cpp:

(JSC::popThunkStackPreservesAndHandleExceptionGenerator):

  • jit/ThunkGenerators.h:
  • runtime/OptionsList.h:

Tools:

Add extra SunSpider run on 32-bit platforms exerciseing baseline JIT
code sharing.

  • Scripts/run-javascriptcore-tests:

(runJSCStressTests):

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/jit/JIT.cpp

    r285795 r286111  
    642642        DEFINE_SLOWCASE_OP(op_del_by_id)
    643643        DEFINE_SLOWCASE_OP(op_sub)
    644 #if !ENABLE(EXTRA_CTI_THUNKS)
    645         DEFINE_SLOWCASE_OP(op_get_from_scope)
    646 #endif
    647644        DEFINE_SLOWCASE_OP(op_put_to_scope)
    648645
     
    813810                    continue;
    814811                int offset = CallFrame::argumentOffsetIncludingThis(argument) * static_cast<int>(sizeof(Register));
    815 #if USE(JSVALUE64)
    816                 constexpr JSValueRegs resultRegs { regT0 };
    817 #elif USE(JSVALUE32_64)
    818                 constexpr JSValueRegs resultRegs { regT1, regT0 };
    819 #endif
    820                 loadValue(Address(callFrameRegister, offset), resultRegs);
    821                 storeValue(resultRegs, Address(regT2, argument * sizeof(ValueProfile) + ValueProfile::offsetOfFirstBucket()));
     812                loadValue(Address(callFrameRegister, offset), jsRegT10);
     813                storeValue(jsRegT10, Address(regT2, argument * sizeof(ValueProfile) + ValueProfile::offsetOfFirstBucket()));
    822814            }
    823815        }
     
    10161008    m_jitCode->adoptMathICs(m_mathICs);
    10171009    m_jitCode->m_constantPool = WTFMove(m_constantPool);
    1018 #if USE(JSVALUE64)
    10191010    m_jitCode->m_isShareable = m_isShareable;
    1020 #else
    1021     m_jitCode->m_isShareable = false;
    1022 #endif
    10231011
    10241012    if (JITInternal::verbose)
     
    10771065
    10781066    if (!m_exceptionChecks.empty()) {
    1079         m_exceptionHandler = label();
    10801067        m_exceptionChecks.link(this);
    10811068
Note: See TracChangeset for help on using the changeset viewer.