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):

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/jsc.cpp

    r198945 r199073  
    2424
    2525#include "ArrayPrototype.h"
     26#include "BuiltinExecutables.h"
    2627#include "ButterflyInlines.h"
    2728#include "BytecodeGenerator.h"
     
    3334#include "Exception.h"
    3435#include "ExceptionHelpers.h"
     36#include "GetterSetter.h"
    3537#include "HeapProfiler.h"
    3638#include "HeapSnapshotBuilder.h"
     
    552554static EncodedJSValue JSC_HOST_CALL functionCreateImpureGetter(ExecState*);
    553555static EncodedJSValue JSC_HOST_CALL functionCreateCustomGetterObject(ExecState*);
     556static EncodedJSValue JSC_HOST_CALL functionCreateBuiltin(ExecState*);
    554557static EncodedJSValue JSC_HOST_CALL functionSetImpureGetterDelegate(ExecState*);
    555558
     
    572575static EncodedJSValue JSC_HOST_CALL functionHeapSize(ExecState*);
    573576static EncodedJSValue JSC_HOST_CALL functionAddressOf(ExecState*);
     577static EncodedJSValue JSC_HOST_CALL functionGetGetterSetter(ExecState*);
    574578#ifndef NDEBUG
    575579static EncodedJSValue JSC_HOST_CALL functionDumpCallFrame(ExecState*);
     
    741745        addFunction(vm, "gcHeapSize", functionHeapSize, 0);
    742746        addFunction(vm, "addressOf", functionAddressOf, 1);
     747        addFunction(vm, "getGetterSetter", functionGetGetterSetter, 2);
    743748#ifndef NDEBUG
    744749        addFunction(vm, "dumpCallFrame", functionDumpCallFrame, 0);
     
    789794        addFunction(vm, "createImpureGetter", functionCreateImpureGetter, 1);
    790795        addFunction(vm, "createCustomGetterObject", functionCreateCustomGetterObject, 0);
     796        addFunction(vm, "createBuiltin", functionCreateBuiltin, 2);
    791797        addFunction(vm, "setImpureGetterDelegate", functionSetImpureGetterDelegate, 2);
    792798
     
    13291335}
    13301336
     1337static EncodedJSValue JSC_HOST_CALL functionGetGetterSetter(ExecState* exec)
     1338{
     1339    JSValue value = exec->argument(0);
     1340    if (!value.isObject())
     1341        return JSValue::encode(jsUndefined());
     1342
     1343    JSValue property = exec->argument(1);
     1344    if (!property.isString())
     1345        return JSValue::encode(jsUndefined());
     1346
     1347    Identifier ident = Identifier::fromString(&exec->vm(), property.toString(exec)->value(exec));
     1348
     1349    PropertySlot slot(value, PropertySlot::InternalMethodType::VMInquiry);
     1350    value.getPropertySlot(exec, ident, slot);
     1351
     1352    JSValue result;
     1353    if (slot.isCacheableGetter())
     1354        result = slot.getterSetter();
     1355    else
     1356        result = jsNull();
     1357
     1358    return JSValue::encode(result);
     1359}
     1360
    13311361EncodedJSValue JSC_HOST_CALL functionVersion(ExecState*)
    13321362{
     
    17111741        return JSValue::encode(exec->vm().throwException(exec, error));
    17121742    return JSValue::encode(jsUndefined());
     1743}
     1744
     1745EncodedJSValue JSC_HOST_CALL functionCreateBuiltin(ExecState* exec)
     1746{
     1747    if (exec->argumentCount() < 1 || !exec->argument(0).isString())
     1748        return JSValue::encode(jsUndefined());
     1749
     1750    String functionText = exec->argument(0).toString(exec)->value(exec);
     1751    if (exec->hadException())
     1752        return JSValue::encode(JSValue());
     1753
     1754    VM& vm = exec->vm();
     1755    const SourceCode& source = makeSource(functionText);
     1756    JSFunction* func = JSFunction::createBuiltinFunction(vm, BuiltinExecutables::createExecutable(vm, source, Identifier::fromString(&vm, "foo"), ConstructorKind::None, ConstructAbility::CannotConstruct)->link(vm, source), exec->lexicalGlobalObject());
     1757
     1758    return JSValue::encode(func);
    17131759}
    17141760
Note: See TracChangeset for help on using the changeset viewer.