Ignore:
Timestamp:
Apr 5, 2016, 2:36:25 PM (9 years ago)
Author:
[email protected]
Message:

We should support the ability to do a non-effectful getById
https://bugs.webkit.org/show_bug.cgi?id=156116

Reviewed by Benjamin Poulain.

Currently, there is no way in JS to do a non-effectful getById. A non-effectful getById is
useful because it enables us to take different code paths based on values that we would
otherwise not be able to have knowledge of. This patch adds this new feature called
try_get_by_id that will attempt to do as much of a get_by_id as possible without performing
an effectful behavior. Thus, try_get_by_id will return the value if the slot is a value, the
GetterSetter object if the slot is a normal accessor (not a CustomGetterSetter) and
undefined if the slot is unset. If the slot is proxied or any other cases then the result
is null. In theory, if we ever wanted to check for null we could add a sentinal object to
the global object that indicates we could not get the result.

In order to implement this feature we add a new enum GetByIdKind that indicates what to do
for accessor properties in PolymorphicAccess. If the GetByIdKind is pure then we treat the
get_by_id the same way we would for load and return the value at the appropriate offset.
Additionally, in order to make sure the we can properly compare the GetterSetter object
with === GetterSetters are now JSObjects. This comes at the cost of eight extra bytes on the
GetterSetter object but it vastly simplifies the patch. Additionally, the extra bytes are
likely to have little to no impact on memory usage as normal accessors are generally rare.

  • JavaScriptCore.xcodeproj/project.pbxproj:
  • builtins/BuiltinExecutables.cpp:

(JSC::BuiltinExecutables::createDefaultConstructor):
(JSC::BuiltinExecutables::createBuiltinExecutable):
(JSC::createBuiltinExecutable):
(JSC::BuiltinExecutables::createExecutable):
(JSC::createExecutableInternal): Deleted.

  • builtins/BuiltinExecutables.h:
  • bytecode/BytecodeIntrinsicRegistry.h:
  • bytecode/BytecodeList.json:
  • bytecode/BytecodeUseDef.h:

(JSC::computeUsesForBytecodeOffset):
(JSC::computeDefsForBytecodeOffset):

  • bytecode/CodeBlock.cpp:

(JSC::CodeBlock::dumpBytecode):

  • bytecode/PolymorphicAccess.cpp:

(JSC::AccessCase::tryGet):
(JSC::AccessCase::generate):
(WTF::printInternal):

  • bytecode/PolymorphicAccess.h:

(JSC::AccessCase::isGet): Deleted.
(JSC::AccessCase::isPut): Deleted.
(JSC::AccessCase::isIn): Deleted.

  • bytecode/StructureStubInfo.cpp:

(JSC::StructureStubInfo::reset):

  • bytecode/StructureStubInfo.h:
  • bytecompiler/BytecodeGenerator.cpp:

(JSC::BytecodeGenerator::emitTryGetById):

  • bytecompiler/BytecodeGenerator.h:
  • bytecompiler/NodesCodegen.cpp:

(JSC::BytecodeIntrinsicNode::emit_intrinsic_tryGetById):

  • dfg/DFGSpeculativeJIT32_64.cpp:

(JSC::DFG::SpeculativeJIT::cachedGetById):

  • dfg/DFGSpeculativeJIT64.cpp:

(JSC::DFG::SpeculativeJIT::cachedGetById):

  • ftl/FTLLowerDFGToB3.cpp:

(JSC::FTL::DFG::LowerDFGToB3::getById):

  • jit/JIT.cpp:

(JSC::JIT::privateCompileMainPass):
(JSC::JIT::privateCompileSlowCases):

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

(JSC::JITGetByIdGenerator::JITGetByIdGenerator):

  • jit/JITInlineCacheGenerator.h:
  • jit/JITInlines.h:

(JSC::JIT::callOperation):

  • jit/JITOperations.cpp:
  • jit/JITOperations.h:
  • jit/JITPropertyAccess.cpp:

(JSC::JIT::emitGetByValWithCachedId):
(JSC::JIT::emit_op_try_get_by_id):
(JSC::JIT::emitSlow_op_try_get_by_id):
(JSC::JIT::emit_op_get_by_id):

  • jit/JITPropertyAccess32_64.cpp:

(JSC::JIT::emitGetByValWithCachedId):
(JSC::JIT::emit_op_try_get_by_id):
(JSC::JIT::emitSlow_op_try_get_by_id):
(JSC::JIT::emit_op_get_by_id):

  • jit/Repatch.cpp:

(JSC::repatchByIdSelfAccess):
(JSC::appropriateOptimizingGetByIdFunction):
(JSC::appropriateGenericGetByIdFunction):
(JSC::tryCacheGetByID):
(JSC::repatchGetByID):
(JSC::resetGetByID):

  • jit/Repatch.h:
  • jsc.cpp:

(GlobalObject::finishCreation):
(functionGetGetterSetter):
(functionCreateBuiltin):

  • llint/LLIntData.cpp:

(JSC::LLInt::Data::performAssertions):

  • llint/LLIntSlowPaths.cpp:

(JSC::LLInt::LLINT_SLOW_PATH_DECL):

  • llint/LLIntSlowPaths.h:
  • llint/LowLevelInterpreter.asm:
  • runtime/GetterSetter.cpp:
  • runtime/GetterSetter.h:
  • runtime/JSType.h:
  • runtime/PropertySlot.cpp:

(JSC::PropertySlot::getPureResult):

  • runtime/PropertySlot.h:
  • runtime/ProxyObject.cpp:

(JSC::ProxyObject::getOwnPropertySlotCommon):

  • tests/stress/try-get-by-id.js: Added.

(tryGetByIdText):
(getCaller.obj.1.throw.new.Error.let.func):
(getCaller.obj.1.throw.new.Error):
(throw.new.Error.get let):
(throw.new.Error.):
(throw.new.Error.let.get createBuiltin):
(get let):
(let.get createBuiltin):
(let.func):
(get let.func):
(get throw):

Location:
trunk/Source/JavaScriptCore/builtins
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/builtins/BuiltinExecutables.cpp

    r197308 r199073  
    3636namespace JSC {
    3737
    38 static UnlinkedFunctionExecutable* createExecutableInternal(VM&, const SourceCode&, const Identifier&, ConstructorKind, ConstructAbility);
    39 
    4038BuiltinExecutables::BuiltinExecutables(VM& vm)
    4139    : m_vm(vm)
     
    5553        break;
    5654    case ConstructorKind::Base:
    57         return createExecutableInternal(m_vm, makeSource(baseConstructorCode), name, constructorKind, ConstructAbility::CanConstruct);
     55        return createExecutable(m_vm, makeSource(baseConstructorCode), name, constructorKind, ConstructAbility::CanConstruct);
    5856    case ConstructorKind::Derived:
    59         return createExecutableInternal(m_vm, makeSource(derivedConstructorCode), name, constructorKind, ConstructAbility::CanConstruct);
     57        return createExecutable(m_vm, makeSource(derivedConstructorCode), name, constructorKind, ConstructAbility::CanConstruct);
    6058    }
    6159    ASSERT_NOT_REACHED();
     
    6563UnlinkedFunctionExecutable* BuiltinExecutables::createBuiltinExecutable(const SourceCode& code, const Identifier& name, ConstructAbility constructAbility)
    6664{
    67     return createExecutableInternal(m_vm, code, name, ConstructorKind::None, constructAbility);
     65    return createExecutable(m_vm, code, name, ConstructorKind::None, constructAbility);
    6866}
    6967
    7068UnlinkedFunctionExecutable* createBuiltinExecutable(VM& vm, const SourceCode& code, const Identifier& name, ConstructAbility constructAbility)
    7169{
    72     return createExecutableInternal(vm, code, name, ConstructorKind::None, constructAbility);
     70    return BuiltinExecutables::createExecutable(vm, code, name, ConstructorKind::None, constructAbility);
    7371}
    7472
    75 UnlinkedFunctionExecutable* createExecutableInternal(VM& vm, const SourceCode& source, const Identifier& name, ConstructorKind constructorKind, ConstructAbility constructAbility)
     73UnlinkedFunctionExecutable* BuiltinExecutables::createExecutable(VM& vm, const SourceCode& source, const Identifier& name, ConstructorKind constructorKind, ConstructAbility constructAbility)
    7674{
    7775    JSTextPosition positionBeforeLastNewline;
  • trunk/Source/JavaScriptCore/builtins/BuiltinExecutables.h

    r191433 r199073  
    5353    UnlinkedFunctionExecutable* createDefaultConstructor(ConstructorKind, const Identifier& name);
    5454
     55    JS_EXPORT_PRIVATE static UnlinkedFunctionExecutable* createExecutable(VM&, const SourceCode&, const Identifier&, ConstructorKind, ConstructAbility);
    5556private:
    5657    void finalize(Handle<Unknown>, void* context) override;
Note: See TracChangeset for help on using the changeset viewer.