Changeset 199170 in webkit


Ignore:
Timestamp:
Apr 7, 2016 12:38:00 PM (8 years ago)
Author:
keith_miller@apple.com
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/BuiltinExecutableCreator.cpp: Added.

(JSC::createBuiltinExecutable):

  • builtins/BuiltinExecutableCreator.h: Copied from Source/JavaScriptCore/builtins/BuiltinExecutables.h.
  • 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
Files:
1 added
40 edited
2 copied

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/ChangeLog

    r199166 r199170  
     12016-04-07  Keith Miller  <keith_miller@apple.com>
     2
     3        We should support the ability to do a non-effectful getById
     4        https://bugs.webkit.org/show_bug.cgi?id=156116
     5
     6        Reviewed by Benjamin Poulain.
     7
     8        Currently, there is no way in JS to do a non-effectful getById. A non-effectful getById is
     9        useful because it enables us to take different code paths based on values that we would
     10        otherwise not be able to have knowledge of. This patch adds this new feature called
     11        try_get_by_id that will attempt to do as much of a get_by_id as possible without performing
     12        an effectful behavior. Thus, try_get_by_id will return the value if the slot is a value, the
     13        GetterSetter object if the slot is a normal accessor (not a CustomGetterSetter) and
     14        undefined if the slot is unset.  If the slot is proxied or any other cases then the result
     15        is null. In theory, if we ever wanted to check for null we could add a sentinal object to
     16        the global object that indicates we could not get the result.
     17
     18        In order to implement this feature we add a new enum GetByIdKind that indicates what to do
     19        for accessor properties in PolymorphicAccess. If the GetByIdKind is pure then we treat the
     20        get_by_id the same way we would for load and return the value at the appropriate offset.
     21        Additionally, in order to make sure the we can properly compare the GetterSetter object
     22        with === GetterSetters are now JSObjects. This comes at the cost of eight extra bytes on the
     23        GetterSetter object but it vastly simplifies the patch. Additionally, the extra bytes are
     24        likely to have little to no impact on memory usage as normal accessors are generally rare.
     25
     26        * JavaScriptCore.xcodeproj/project.pbxproj:
     27        * builtins/BuiltinExecutableCreator.cpp: Added.
     28        (JSC::createBuiltinExecutable):
     29        * builtins/BuiltinExecutableCreator.h: Copied from Source/JavaScriptCore/builtins/BuiltinExecutables.h.
     30        * builtins/BuiltinExecutables.cpp:
     31        (JSC::BuiltinExecutables::createDefaultConstructor):
     32        (JSC::BuiltinExecutables::createBuiltinExecutable):
     33        (JSC::createBuiltinExecutable):
     34        (JSC::BuiltinExecutables::createExecutable):
     35        (JSC::createExecutableInternal): Deleted.
     36        * builtins/BuiltinExecutables.h:
     37        * bytecode/BytecodeIntrinsicRegistry.h:
     38        * bytecode/BytecodeList.json:
     39        * bytecode/BytecodeUseDef.h:
     40        (JSC::computeUsesForBytecodeOffset):
     41        (JSC::computeDefsForBytecodeOffset):
     42        * bytecode/CodeBlock.cpp:
     43        (JSC::CodeBlock::dumpBytecode):
     44        * bytecode/PolymorphicAccess.cpp:
     45        (JSC::AccessCase::tryGet):
     46        (JSC::AccessCase::generate):
     47        (WTF::printInternal):
     48        * bytecode/PolymorphicAccess.h:
     49        (JSC::AccessCase::isGet): Deleted.
     50        (JSC::AccessCase::isPut): Deleted.
     51        (JSC::AccessCase::isIn): Deleted.
     52        * bytecode/StructureStubInfo.cpp:
     53        (JSC::StructureStubInfo::reset):
     54        * bytecode/StructureStubInfo.h:
     55        * bytecompiler/BytecodeGenerator.cpp:
     56        (JSC::BytecodeGenerator::emitTryGetById):
     57        * bytecompiler/BytecodeGenerator.h:
     58        * bytecompiler/NodesCodegen.cpp:
     59        (JSC::BytecodeIntrinsicNode::emit_intrinsic_tryGetById):
     60        * dfg/DFGSpeculativeJIT32_64.cpp:
     61        (JSC::DFG::SpeculativeJIT::cachedGetById):
     62        * dfg/DFGSpeculativeJIT64.cpp:
     63        (JSC::DFG::SpeculativeJIT::cachedGetById):
     64        * ftl/FTLLowerDFGToB3.cpp:
     65        (JSC::FTL::DFG::LowerDFGToB3::getById):
     66        * jit/JIT.cpp:
     67        (JSC::JIT::privateCompileMainPass):
     68        (JSC::JIT::privateCompileSlowCases):
     69        * jit/JIT.h:
     70        * jit/JITInlineCacheGenerator.cpp:
     71        (JSC::JITGetByIdGenerator::JITGetByIdGenerator):
     72        * jit/JITInlineCacheGenerator.h:
     73        * jit/JITInlines.h:
     74        (JSC::JIT::callOperation):
     75        * jit/JITOperations.cpp:
     76        * jit/JITOperations.h:
     77        * jit/JITPropertyAccess.cpp:
     78        (JSC::JIT::emitGetByValWithCachedId):
     79        (JSC::JIT::emit_op_try_get_by_id):
     80        (JSC::JIT::emitSlow_op_try_get_by_id):
     81        (JSC::JIT::emit_op_get_by_id):
     82        * jit/JITPropertyAccess32_64.cpp:
     83        (JSC::JIT::emitGetByValWithCachedId):
     84        (JSC::JIT::emit_op_try_get_by_id):
     85        (JSC::JIT::emitSlow_op_try_get_by_id):
     86        (JSC::JIT::emit_op_get_by_id):
     87        * jit/Repatch.cpp:
     88        (JSC::repatchByIdSelfAccess):
     89        (JSC::appropriateOptimizingGetByIdFunction):
     90        (JSC::appropriateGenericGetByIdFunction):
     91        (JSC::tryCacheGetByID):
     92        (JSC::repatchGetByID):
     93        (JSC::resetGetByID):
     94        * jit/Repatch.h:
     95        * jsc.cpp:
     96        (GlobalObject::finishCreation):
     97        (functionGetGetterSetter):
     98        (functionCreateBuiltin):
     99        * llint/LLIntData.cpp:
     100        (JSC::LLInt::Data::performAssertions):
     101        * llint/LLIntSlowPaths.cpp:
     102        (JSC::LLInt::LLINT_SLOW_PATH_DECL):
     103        * llint/LLIntSlowPaths.h:
     104        * llint/LowLevelInterpreter.asm:
     105        * runtime/GetterSetter.cpp:
     106        * runtime/GetterSetter.h:
     107        * runtime/JSType.h:
     108        * runtime/PropertySlot.cpp:
     109        (JSC::PropertySlot::getPureResult):
     110        * runtime/PropertySlot.h:
     111        * runtime/ProxyObject.cpp:
     112        (JSC::ProxyObject::getOwnPropertySlotCommon):
     113        * tests/stress/try-get-by-id.js: Added.
     114        (tryGetByIdText):
     115        (getCaller.obj.1.throw.new.Error.let.func):
     116        (getCaller.obj.1.throw.new.Error):
     117        (throw.new.Error.get let):
     118        (throw.new.Error.):
     119        (throw.new.Error.let.get createBuiltin):
     120        (get let):
     121        (let.get createBuiltin):
     122        (let.func):
     123        (get let.func):
     124        (get throw):
     125
    11262016-04-07  Filip Pizlo  <fpizlo@apple.com>
    2127
  • trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj

    r199164 r199170  
    19961996                DC17E8191C9C91DB008A6AB3 /* ShadowChickenInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = DC17E8151C9C7FD4008A6AB3 /* ShadowChickenInlines.h */; };
    19971997                DC17E81A1C9C91E9008A6AB3 /* CCallHelpers.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DC17E8161C9C802B008A6AB3 /* CCallHelpers.cpp */; };
     1998                DE26E9031CB5DD0500D2BE82 /* BuiltinExecutableCreator.h in Headers */ = {isa = PBXBuildFile; fileRef = DE26E9021CB5DD0500D2BE82 /* BuiltinExecutableCreator.h */; };
     1999                DE26E9071CB5DEFB00D2BE82 /* BuiltinExecutableCreator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DE26E9061CB5DD9600D2BE82 /* BuiltinExecutableCreator.cpp */; };
    19982000                DE5A0A001BA3AC3E003D4424 /* IntrinsicEmitter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DE5A09FF1BA3AC3E003D4424 /* IntrinsicEmitter.cpp */; };
    19992001                DEA7E2441BBC677200D78440 /* JSTypedArrayViewPrototype.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 53F256E11B87E28000B4B768 /* JSTypedArrayViewPrototype.cpp */; };
     
    42054207                DC17E8151C9C7FD4008A6AB3 /* ShadowChickenInlines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ShadowChickenInlines.h; sourceTree = "<group>"; };
    42064208                DC17E8161C9C802B008A6AB3 /* CCallHelpers.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CCallHelpers.cpp; sourceTree = "<group>"; };
     4209                DE26E9021CB5DD0500D2BE82 /* BuiltinExecutableCreator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BuiltinExecutableCreator.h; sourceTree = "<group>"; };
     4210                DE26E9061CB5DD9600D2BE82 /* BuiltinExecutableCreator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = BuiltinExecutableCreator.cpp; sourceTree = "<group>"; };
    42074211                DE5A09FF1BA3AC3E003D4424 /* IntrinsicEmitter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = IntrinsicEmitter.cpp; sourceTree = "<group>"; };
    42084212                E124A8F50E555775003091F1 /* OpaqueJSString.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OpaqueJSString.h; sourceTree = "<group>"; };
     
    68396843                                7CF9BC581B65D9A3009DB1EF /* ArrayConstructor.js */,
    68406844                                7CF9BC591B65D9A3009DB1EF /* ArrayIteratorPrototype.js */,
     6845                                DE26E9061CB5DD9600D2BE82 /* BuiltinExecutableCreator.cpp */,
     6846                                DE26E9021CB5DD0500D2BE82 /* BuiltinExecutableCreator.h */,
    68416847                                A7D801A11880D66E0026C39B /* BuiltinExecutables.cpp */,
    68426848                                A7D801A21880D66E0026C39B /* BuiltinExecutables.h */,
     
    73847390                                0F56A1D315000F35002992B1 /* ExecutionCounter.h in Headers */,
    73857391                                0F3AC754188E5EC80032029F /* ExitingJITType.h in Headers */,
     7392                                DE26E9031CB5DD0500D2BE82 /* BuiltinExecutableCreator.h in Headers */,
    73867393                                0FB105861675481200F8AB6E /* ExitKind.h in Headers */,
    73877394                                0F0B83AB14BCF5BB00885B4F /* ExpressionRangeInfo.h in Headers */,
     
    87788785                                0F38B01717CFE75500B144D3 /* DFGCompilationKey.cpp in Sources */,
    87798786                                0F38B01917CFE75500B144D3 /* DFGCompilationMode.cpp in Sources */,
     8787                                DE26E9071CB5DEFB00D2BE82 /* BuiltinExecutableCreator.cpp in Sources */,
    87808788                                0F3B3A1A153E68F2003ED0FF /* DFGConstantFoldingPhase.cpp in Sources */,
    87818789                                0FED67B91B26256D0066CE15 /* DFGConstantHoistingPhase.cpp in Sources */,
  • trunk/Source/JavaScriptCore/builtins/BuiltinExecutableCreator.cpp

    r199169 r199170  
    11/*
    2  * Copyright (C) 2014 Apple Inc. All rights reserved.
     2 * Copyright (C) 2016 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    2424 */
    2525
    26 #ifndef BuiltinExecutables_h
    27 #define BuiltinExecutables_h
     26#include "config.h"
     27#include "BuiltinExecutableCreator.h"
    2828
    29 #include "JSCBuiltins.h"
    30 #include "ParserModes.h"
    31 #include "SourceCode.h"
    32 #include "Weak.h"
    33 #include "WeakHandleOwner.h"
     29#include "BuiltinExecutables.h"
    3430
    3531namespace JSC {
    3632
    37 class UnlinkedFunctionExecutable;
    38 class Identifier;
    39 class VM;
    40 
    41 class BuiltinExecutables final: private WeakHandleOwner {
    42     WTF_MAKE_FAST_ALLOCATED;
    43 public:
    44     explicit BuiltinExecutables(VM&);
    45 
    46 #define EXPOSE_BUILTIN_EXECUTABLES(name, functionName, length) \
    47 UnlinkedFunctionExecutable* name##Executable(); \
    48 const SourceCode& name##Source() { return m_##name##Source; }
     33UnlinkedFunctionExecutable* createBuiltinExecutable(VM& vm, const SourceCode& source, const Identifier& ident, ConstructorKind kind, ConstructAbility ability)
     34{
     35    return BuiltinExecutables::createExecutable(vm, source, ident, kind, ability);
     36}
    4937   
    50     JSC_FOREACH_BUILTIN_CODE(EXPOSE_BUILTIN_EXECUTABLES)
    51 #undef EXPOSE_BUILTIN_SOURCES
    52 
    53     UnlinkedFunctionExecutable* createDefaultConstructor(ConstructorKind, const Identifier& name);
    54 
    55 private:
    56     void finalize(Handle<Unknown>, void* context) override;
    57 
    58     VM& m_vm;
    59 
    60     UnlinkedFunctionExecutable* createBuiltinExecutable(const SourceCode&, const Identifier&, ConstructAbility);
    61 
    62 #define DECLARE_BUILTIN_SOURCE_MEMBERS(name, functionName, length)\
    63     SourceCode m_##name##Source; \
    64     Weak<UnlinkedFunctionExecutable> m_##name##Executable;
    65     JSC_FOREACH_BUILTIN_CODE(DECLARE_BUILTIN_SOURCE_MEMBERS)
    66 #undef DECLARE_BUILTIN_SOURCE_MEMBERS
    67 };
    68 
    69 }
    70 
    71 #endif
     38} // namespace JSC
  • trunk/Source/JavaScriptCore/builtins/BuiltinExecutableCreator.h

    r199169 r199170  
    11/*
    2  * Copyright (C) 2014 Apple Inc. All rights reserved.
     2 * Copyright (C) 2016 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    2424 */
    2525
    26 #ifndef BuiltinExecutables_h
    27 #define BuiltinExecutables_h
     26#ifndef BuiltinExecutableCreator_h
     27#define BuiltinExecutableCreator_h
    2828
    29 #include "JSCBuiltins.h"
     29#include "ConstructAbility.h"
    3030#include "ParserModes.h"
    3131#include "SourceCode.h"
    32 #include "Weak.h"
    33 #include "WeakHandleOwner.h"
    3432
    3533namespace JSC {
    3634
    37 class UnlinkedFunctionExecutable;
    38 class Identifier;
    39 class VM;
     35JS_EXPORT_PRIVATE UnlinkedFunctionExecutable* createBuiltinExecutable(VM&, const SourceCode&, const Identifier&, ConstructorKind, ConstructAbility);
    4036
    41 class BuiltinExecutables final: private WeakHandleOwner {
    42     WTF_MAKE_FAST_ALLOCATED;
    43 public:
    44     explicit BuiltinExecutables(VM&);
     37} // namespace JSC
    4538
    46 #define EXPOSE_BUILTIN_EXECUTABLES(name, functionName, length) \
    47 UnlinkedFunctionExecutable* name##Executable(); \
    48 const SourceCode& name##Source() { return m_##name##Source; }
    49    
    50     JSC_FOREACH_BUILTIN_CODE(EXPOSE_BUILTIN_EXECUTABLES)
    51 #undef EXPOSE_BUILTIN_SOURCES
    52 
    53     UnlinkedFunctionExecutable* createDefaultConstructor(ConstructorKind, const Identifier& name);
    54 
    55 private:
    56     void finalize(Handle<Unknown>, void* context) override;
    57 
    58     VM& m_vm;
    59 
    60     UnlinkedFunctionExecutable* createBuiltinExecutable(const SourceCode&, const Identifier&, ConstructAbility);
    61 
    62 #define DECLARE_BUILTIN_SOURCE_MEMBERS(name, functionName, length)\
    63     SourceCode m_##name##Source; \
    64     Weak<UnlinkedFunctionExecutable> m_##name##Executable;
    65     JSC_FOREACH_BUILTIN_CODE(DECLARE_BUILTIN_SOURCE_MEMBERS)
    66 #undef DECLARE_BUILTIN_SOURCE_MEMBERS
    67 };
    68 
    69 }
    70 
    71 #endif
     39#endif /* BuiltinExecutableCreator_h */
  • trunk/Source/JavaScriptCore/builtins/BuiltinExecutables.cpp

    r199108 r199170  
    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

    r199108 r199170  
    5353    UnlinkedFunctionExecutable* createDefaultConstructor(ConstructorKind, const Identifier& name);
    5454
     55    static UnlinkedFunctionExecutable* createExecutable(VM&, const SourceCode&, const Identifier&, ConstructorKind, ConstructAbility);
    5556private:
    5657    void finalize(Handle<Unknown>, void* context) override;
  • trunk/Source/JavaScriptCore/bytecode/BytecodeIntrinsicRegistry.h

    r199164 r199170  
    4242    macro(assert) \
    4343    macro(isObject) \
     44    macro(tryGetById) \
    4445    macro(putByValDirect) \
    4546    macro(toString)
  • trunk/Source/JavaScriptCore/bytecode/BytecodeList.json

    r199108 r199170  
    5858            { "name" : "op_is_function", "length" : 3 },
    5959            { "name" : "op_in", "length" : 4 },
     60            { "name" : "op_try_get_by_id", "length" : 4 },
    6061            { "name" : "op_get_by_id", "length" : 9  },
    6162            { "name" : "op_get_array_length", "length" : 9 },
  • trunk/Source/JavaScriptCore/bytecode/BytecodeUseDef.h

    r199108 r199170  
    144144    case op_get_from_scope:
    145145    case op_to_primitive:
     146    case op_try_get_by_id:
    146147    case op_get_by_id:
    147148    case op_get_array_length:
     
    368369    case op_call_eval:
    369370    case op_construct:
     371    case op_try_get_by_id:
    370372    case op_get_by_id:
    371373    case op_get_array_length:
  • trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp

    r199108 r199170  
    10941094        case op_in: {
    10951095            printBinaryOp(out, exec, location, it, "in");
     1096            break;
     1097        }
     1098        case op_try_get_by_id: {
     1099            int r0 = (++it)->u.operand;
     1100            int r1 = (++it)->u.operand;
     1101            int id0 = (++it)->u.operand;
     1102            printLocationAndOp(out, exec, location, it, "try_get_by_id");
     1103            out.printf("%s, %s, %s", registerName(r0).data(), registerName(r1).data(), idName(id0, identifier(id0)).data());
    10961104            break;
    10971105        }
  • trunk/Source/JavaScriptCore/bytecode/PolymorphicAccess.cpp

    r199166 r199170  
    160160}
    161161
     162std::unique_ptr<AccessCase> AccessCase::tryGet(
     163    VM& vm, JSCell* owner, AccessType type, PropertyOffset offset, Structure* structure,
     164    const ObjectPropertyConditionSet& conditionSet, bool viaProxy, WatchpointSet* additionalSet)
     165{
     166    std::unique_ptr<AccessCase> result(new AccessCase());
     167
     168    result->m_type = type;
     169    result->m_offset = offset;
     170    result->m_structure.set(vm, owner, structure);
     171    result->m_conditionSet = conditionSet;
     172
     173    if (viaProxy || additionalSet) {
     174        result->m_rareData = std::make_unique<RareData>();
     175        result->m_rareData->viaProxy = viaProxy;
     176        result->m_rareData->additionalSet = additionalSet;
     177    }
     178
     179    return result;
     180}
     181
    162182std::unique_ptr<AccessCase> AccessCase::get(
    163183    VM& vm, JSCell* owner, AccessType type, PropertyOffset offset, Structure* structure,
     
    686706
    687707    case Load:
     708    case GetGetter:
    688709    case Getter:
    689710    case Setter:
     
    721742        GPRReg loadedValueGPR = InvalidGPRReg;
    722743        if (m_type != CustomValueGetter && m_type != CustomAccessorGetter && m_type != CustomValueSetter && m_type != CustomAccessorSetter) {
    723             if (m_type == Load)
     744            if (m_type == Load || m_type == GetGetter)
    724745                loadedValueGPR = valueRegs.payloadGPR();
    725746            else
     
    740761                CCallHelpers::Address(storageGPR, offsetRelativeToBase(m_offset)), loadedValueGPR);
    741762#else
    742             if (m_type == Load) {
     763            if (m_type == Load || m_type == GetGetter) {
    743764                jit.load32(
    744765                    CCallHelpers::Address(storageGPR, offsetRelativeToBase(m_offset) + TagOffset),
     
    751772        }
    752773
    753         if (m_type == Load) {
     774        if (m_type == Load || m_type == GetGetter) {
    754775            state.succeed();
    755776            return;
     
    15681589        out.print("Miss");
    15691590        return;
     1591    case AccessCase::GetGetter:
     1592        out.print("GetGetter");
     1593        return;
    15701594    case AccessCase::Getter:
    15711595        out.print("Getter");
  • trunk/Source/JavaScriptCore/bytecode/PolymorphicAccess.h

    r199108 r199170  
    5858        Replace,
    5959        Miss,
     60        GetGetter,
    6061        Getter,
    6162        Setter,
     
    7172    };
    7273
    73     static bool isGet(AccessType type)
    74     {
    75         switch (type) {
    76         case Transition:
    77         case Replace:
    78         case Setter:
    79         case CustomValueSetter:
    80         case CustomAccessorSetter:
    81         case InHit:
    82         case InMiss:
    83             return false;
    84         case Load:
    85         case MegamorphicLoad:
    86         case Miss:
    87         case Getter:
    88         case CustomValueGetter:
    89         case CustomAccessorGetter:
    90         case IntrinsicGetter:
    91         case ArrayLength:
    92         case StringLength:
    93             return true;
    94         }
    95     }
    96 
    97     static bool isPut(AccessType type)
    98     {
    99         switch (type) {
    100         case Load:
    101         case MegamorphicLoad:
    102         case Miss:
    103         case Getter:
    104         case CustomValueGetter:
    105         case CustomAccessorGetter:
    106         case IntrinsicGetter:
    107         case InHit:
    108         case InMiss:
    109         case ArrayLength:
    110         case StringLength:
    111             return false;
    112         case Transition:
    113         case Replace:
    114         case Setter:
    115         case CustomValueSetter:
    116         case CustomAccessorSetter:
    117             return true;
    118         }
    119     }
    120 
    121     static bool isIn(AccessType type)
    122     {
    123         switch (type) {
    124         case Load:
    125         case MegamorphicLoad:
    126         case Miss:
    127         case Getter:
    128         case CustomValueGetter:
    129         case CustomAccessorGetter:
    130         case IntrinsicGetter:
    131         case Transition:
    132         case Replace:
    133         case Setter:
    134         case CustomValueSetter:
    135         case CustomAccessorSetter:
    136         case ArrayLength:
    137         case StringLength:
    138             return false;
    139         case InHit:
    140         case InMiss:
    141             return true;
    142         }
    143     }
     74    static std::unique_ptr<AccessCase> tryGet(
     75        VM&, JSCell* owner, AccessType, PropertyOffset, Structure*,
     76        const ObjectPropertyConditionSet& = ObjectPropertyConditionSet(),
     77        bool viaProxy = false,
     78        WatchpointSet* additionalSet = nullptr);
    14479
    14580    static std::unique_ptr<AccessCase> get(
  • trunk/Source/JavaScriptCore/bytecode/StructureStubInfo.cpp

    r199162 r199170  
    149149
    150150    switch (accessType) {
     151    case AccessType::GetPure:
     152        resetGetByID(codeBlock, *this, GetByIDKind::Pure);
     153        break;
    151154    case AccessType::Get:
    152         resetGetByID(codeBlock, *this);
     155        resetGetByID(codeBlock, *this, GetByIDKind::Normal);
    153156        break;
    154157    case AccessType::Put:
  • trunk/Source/JavaScriptCore/bytecode/StructureStubInfo.h

    r199108 r199170  
    4848enum class AccessType : int8_t {
    4949    Get,
     50    GetPure,
    5051    Put,
    5152    In
  • trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp

    r199108 r199170  
    23582358    instructions().append(constructor->index());
    23592359    instructions().append(hasInstanceValue->index());
     2360    return dst;
     2361}
     2362
     2363RegisterID* BytecodeGenerator::emitTryGetById(RegisterID* dst, RegisterID* base, const Identifier& property)
     2364{
     2365    ASSERT_WITH_MESSAGE(!parseIndex(property), "Indexed properties are not supported with tryGetById.");
     2366
     2367    emitOpcode(op_try_get_by_id);
     2368    instructions().append(kill(dst));
     2369    instructions().append(base->index());
     2370    instructions().append(addConstant(property));
    23602371    return dst;
    23612372}
  • trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h

    r199108 r199170  
    541541        RegisterID* emitIn(RegisterID* dst, RegisterID* property, RegisterID* base) { return emitBinaryOp(op_in, dst, property, base, OperandTypes()); }
    542542
     543        RegisterID* emitTryGetById(RegisterID* dst, RegisterID* base, const Identifier& property);
    543544        RegisterID* emitGetById(RegisterID* dst, RegisterID* base, const Identifier& property);
    544545        RegisterID* emitPutById(RegisterID* base, const Identifier& property, RegisterID* value);
  • trunk/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp

    r199108 r199170  
    841841
    842842    return generator.moveToDestinationIfNeeded(dst, generator.emitDirectPutByVal(base.get(), index.get(), value.get()));
     843}
     844
     845RegisterID* BytecodeIntrinsicNode::emit_intrinsic_tryGetById(BytecodeGenerator& generator, RegisterID* dst)
     846{
     847    ArgumentListNode* node = m_args->m_listNode;
     848    RefPtr<RegisterID> base = generator.emitNode(node);
     849    node = node->m_next;
     850
     851    // Since this is a builtin we expect the creator to use a string literal as the second argument.
     852    ASSERT(node->m_expr->isString());
     853    const Identifier& ident = static_cast<StringNode*>(node->m_expr)->value();
     854    ASSERT(!node->m_next);
     855
     856    RegisterID* finalDest = generator.finalDestination(dst);
     857    return generator.emitTryGetById(finalDest, base.get(), ident);
    843858}
    844859
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp

    r199164 r199170  
    195195        m_jit.codeBlock(), codeOrigin, callSite, usedRegisters,
    196196        JSValueRegs(baseTagGPROrNone, basePayloadGPR),
    197         JSValueRegs(resultTagGPR, resultPayloadGPR));
     197        JSValueRegs(resultTagGPR, resultPayloadGPR), AccessType::Get);
    198198   
    199199    gen.generateFastPath(m_jit);
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp

    r199164 r199170  
    165165    JITGetByIdGenerator gen(
    166166        m_jit.codeBlock(), codeOrigin, callSite, usedRegisters, JSValueRegs(baseGPR),
    167         JSValueRegs(resultGPR));
     167        JSValueRegs(resultGPR), AccessType::Get);
    168168    gen.generateFastPath(m_jit);
    169169   
  • trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp

    r199164 r199170  
    73327332                    jit.codeBlock(), node->origin.semantic, callSiteIndex,
    73337333                    params.unavailableRegisters(), JSValueRegs(params[1].gpr()),
    7334                     JSValueRegs(params[0].gpr()));
     7334                    JSValueRegs(params[0].gpr()), AccessType::Get);
    73357335
    73367336                generator->generateFastPath(jit);
  • trunk/Source/JavaScriptCore/jit/JIT.cpp

    r199108 r199170  
    229229        DEFINE_OP(op_eq)
    230230        DEFINE_OP(op_eq_null)
     231        DEFINE_OP(op_try_get_by_id)
    231232        case op_get_array_length:
    232233        DEFINE_OP(op_get_by_id)
     
    407408        DEFINE_SLOWCASE_OP(op_div)
    408409        DEFINE_SLOWCASE_OP(op_eq)
     410        DEFINE_SLOWCASE_OP(op_try_get_by_id)
    409411        case op_get_array_length:
    410412        DEFINE_SLOWCASE_OP(op_get_by_id)
  • trunk/Source/JavaScriptCore/jit/JIT.h

    r199108 r199170  
    503503        void emit_op_eq(Instruction*);
    504504        void emit_op_eq_null(Instruction*);
     505        void emit_op_try_get_by_id(Instruction*);
    505506        void emit_op_get_by_id(Instruction*);
    506507        void emit_op_get_arguments_length(Instruction*);
     
    615616        void emitSlow_op_eq(Instruction*, Vector<SlowCaseEntry>::iterator&);
    616617        void emitSlow_op_get_callee(Instruction*, Vector<SlowCaseEntry>::iterator&);
     618        void emitSlow_op_try_get_by_id(Instruction*, Vector<SlowCaseEntry>::iterator&);
    617619        void emitSlow_op_get_by_id(Instruction*, Vector<SlowCaseEntry>::iterator&);
    618620        void emitSlow_op_get_arguments_length(Instruction*, Vector<SlowCaseEntry>::iterator&);
     
    739741        MacroAssembler::Call callOperation(J_JITOperation_EJ, int, GPRReg);
    740742#if USE(JSVALUE64)
     743        MacroAssembler::Call callOperation(J_JITOperation_ESsiJI, int, StructureStubInfo*, GPRReg, UniquedStringImpl*);
    741744        MacroAssembler::Call callOperation(WithProfileTag, J_JITOperation_ESsiJI, int, StructureStubInfo*, GPRReg, UniquedStringImpl*);
    742745#else
     746        MacroAssembler::Call callOperation(J_JITOperation_ESsiJI, int, StructureStubInfo*, GPRReg, GPRReg, UniquedStringImpl*);
    743747        MacroAssembler::Call callOperation(WithProfileTag, J_JITOperation_ESsiJI, int, StructureStubInfo*, GPRReg, GPRReg, UniquedStringImpl*);
    744748#endif
  • trunk/Source/JavaScriptCore/jit/JITInlineCacheGenerator.cpp

    r199108 r199170  
    105105JITGetByIdGenerator::JITGetByIdGenerator(
    106106    CodeBlock* codeBlock, CodeOrigin codeOrigin, CallSiteIndex callSite, const RegisterSet& usedRegisters,
    107     JSValueRegs base, JSValueRegs value)
     107    JSValueRegs base, JSValueRegs value, AccessType accessType)
    108108    : JITByIdGenerator(
    109         codeBlock, codeOrigin, callSite, AccessType::Get, usedRegisters, base, value)
     109        codeBlock, codeOrigin, callSite, accessType, usedRegisters, base, value)
    110110{
    111111    RELEASE_ASSERT(base.payloadGPR() != value.tagGPR());
  • trunk/Source/JavaScriptCore/jit/JITInlineCacheGenerator.h

    r199108 r199170  
    9797    JITGetByIdGenerator(
    9898        CodeBlock*, CodeOrigin, CallSiteIndex, const RegisterSet& usedRegisters, JSValueRegs base,
    99         JSValueRegs value);
     99        JSValueRegs value, AccessType);
    100100   
    101101    void generateFastPath(MacroAssembler&);
  • trunk/Source/JavaScriptCore/jit/JITInlines.h

    r199108 r199170  
    460460}
    461461
     462ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(J_JITOperation_ESsiJI operation, int dst, StructureStubInfo* stubInfo, GPRReg arg1, UniquedStringImpl* uid)
     463{
     464    setupArgumentsWithExecState(TrustedImmPtr(stubInfo), arg1, TrustedImmPtr(uid));
     465    return appendCallWithExceptionCheckSetJSValueResult(operation, dst);
     466}
     467
    462468ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(JIT::WithProfileTag, J_JITOperation_ESsiJI operation, int dst, StructureStubInfo* stubInfo, GPRReg arg1, UniquedStringImpl* uid)
    463469{
     
    640646{
    641647    setupArgumentsWithExecState(EABI_32BIT_DUMMY_ARG arg1Payload, arg1Tag);
     648    return appendCallWithExceptionCheckSetJSValueResult(operation, dst);
     649}
     650
     651ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(J_JITOperation_ESsiJI operation, int dst, StructureStubInfo* stubInfo, GPRReg arg1Tag, GPRReg arg1Payload, UniquedStringImpl* uid)
     652{
     653    setupArgumentsWithExecState(TrustedImmPtr(stubInfo), arg1Payload, arg1Tag, TrustedImmPtr(uid));
    642654    return appendCallWithExceptionCheckSetJSValueResult(operation, dst);
    643655}
  • trunk/Source/JavaScriptCore/jit/JITOperations.cpp

    r199140 r199170  
    157157}
    158158
     159EncodedJSValue JIT_OPERATION operationTryGetById(ExecState* exec, StructureStubInfo* stubInfo, EncodedJSValue base, UniquedStringImpl* uid)
     160{
     161    VM* vm = &exec->vm();
     162    NativeCallFrameTracer tracer(vm, exec);
     163    Identifier ident = Identifier::fromUid(vm, uid);
     164    stubInfo->tookSlowPath = true;
     165
     166    JSValue baseValue = JSValue::decode(base);
     167    PropertySlot slot(baseValue, PropertySlot::InternalMethodType::VMInquiry);
     168    baseValue.getPropertySlot(exec, ident, slot);
     169
     170    return JSValue::encode(slot.getPureResult());
     171}
     172
     173EncodedJSValue JIT_OPERATION operationTryGetByIdOptimize(ExecState* exec, StructureStubInfo* stubInfo, EncodedJSValue base, UniquedStringImpl* uid)
     174{
     175    VM* vm = &exec->vm();
     176    NativeCallFrameTracer tracer(vm, exec);
     177    Identifier ident = Identifier::fromUid(vm, uid);
     178
     179    JSValue baseValue = JSValue::decode(base);
     180    PropertySlot slot(baseValue, PropertySlot::InternalMethodType::VMInquiry);
     181
     182    baseValue.getPropertySlot(exec, ident, slot);
     183    if (stubInfo->considerCaching() && !slot.isTaintedByProxy() && (slot.isCacheableValue() || slot.isCacheableGetter() || slot.isUnset()))
     184        repatchGetByID(exec, baseValue, ident, slot, *stubInfo, GetByIDKind::Pure);
     185
     186    return JSValue::encode(slot.getPureResult());
     187}
     188
    159189EncodedJSValue JIT_OPERATION operationGetById(ExecState* exec, StructureStubInfo* stubInfo, EncodedJSValue base, UniquedStringImpl* uid)
    160190{
     
    196226    bool hasResult = baseValue.getPropertySlot(exec, ident, slot);
    197227    if (stubInfo->considerCaching())
    198         repatchGetByID(exec, baseValue, ident, slot, *stubInfo);
     228        repatchGetByID(exec, baseValue, ident, slot, *stubInfo, GetByIDKind::Normal);
    199229   
    200230    return JSValue::encode(hasResult? slot.getValue(exec, ident) : jsUndefined());
  • trunk/Source/JavaScriptCore/jit/JITOperations.h

    r199164 r199170  
    288288int32_t JIT_OPERATION operationCallArityCheck(ExecState*) WTF_INTERNAL;
    289289int32_t JIT_OPERATION operationConstructArityCheck(ExecState*) WTF_INTERNAL;
     290EncodedJSValue JIT_OPERATION operationTryGetById(ExecState*, StructureStubInfo*, EncodedJSValue, UniquedStringImpl*) WTF_INTERNAL;
     291EncodedJSValue JIT_OPERATION operationTryGetByIdOptimize(ExecState*, StructureStubInfo*, EncodedJSValue, UniquedStringImpl*) WTF_INTERNAL;
    290292EncodedJSValue JIT_OPERATION operationGetById(ExecState*, StructureStubInfo*, EncodedJSValue, UniquedStringImpl*) WTF_INTERNAL;
    291293EncodedJSValue JIT_OPERATION operationGetByIdGeneric(ExecState*, EncodedJSValue, UniquedStringImpl*) WTF_INTERNAL;
    292 EncodedJSValue JIT_OPERATION operationGetByIdBuildList(ExecState*, StructureStubInfo*, EncodedJSValue, UniquedStringImpl*) WTF_INTERNAL;
    293294EncodedJSValue JIT_OPERATION operationGetByIdOptimize(ExecState*, StructureStubInfo*, EncodedJSValue, UniquedStringImpl*) WTF_INTERNAL;
    294295EncodedJSValue JIT_OPERATION operationInOptimize(ExecState*, StructureStubInfo*, JSCell*, UniquedStringImpl*) WTF_INTERNAL;
  • trunk/Source/JavaScriptCore/jit/JITPropertyAccess.cpp

    r199108 r199170  
    214214    JITGetByIdGenerator gen(
    215215        m_codeBlock, CodeOrigin(m_bytecodeOffset), CallSiteIndex(m_bytecodeOffset), RegisterSet::stubUnavailableRegisters(),
    216         JSValueRegs(regT0), JSValueRegs(regT0));
     216        JSValueRegs(regT0), JSValueRegs(regT0), AccessType::Get);
    217217    gen.generateFastPath(*this);
    218218
     
    532532}
    533533
    534 void JIT::emit_op_get_by_id(Instruction* currentInstruction)
     534void JIT::emit_op_try_get_by_id(Instruction* currentInstruction)
     535{
     536    int resultVReg = currentInstruction[1].u.operand;
     537    int baseVReg = currentInstruction[2].u.operand;
     538
     539    emitGetVirtualRegister(baseVReg, regT0);
     540
     541    emitJumpSlowCaseIfNotJSCell(regT0, baseVReg);
     542
     543    JITGetByIdGenerator gen(
     544        m_codeBlock, CodeOrigin(m_bytecodeOffset), CallSiteIndex(m_bytecodeOffset), RegisterSet::stubUnavailableRegisters(),
     545        JSValueRegs(regT0), JSValueRegs(regT0), AccessType::GetPure);
     546    gen.generateFastPath(*this);
     547    addSlowCase(gen.slowPathJump());
     548    m_getByIds.append(gen);
     549   
     550    emitPutVirtualRegister(resultVReg);
     551}
     552
     553void JIT::emitSlow_op_try_get_by_id(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
    535554{
    536555    int resultVReg = currentInstruction[1].u.operand;
     
    538557    const Identifier* ident = &(m_codeBlock->identifier(currentInstruction[3].u.operand));
    539558
     559    linkSlowCaseIfNotJSCell(iter, baseVReg);
     560    linkSlowCase(iter);
     561
     562    JITGetByIdGenerator& gen = m_getByIds[m_getByIdIndex++];
     563
     564    Label coldPathBegin = label();
     565
     566    Call call = callOperation(operationTryGetByIdOptimize, resultVReg, gen.stubInfo(), regT0, ident->impl());
     567   
     568    gen.reportSlowPathCall(coldPathBegin, call);
     569}
     570
     571void JIT::emit_op_get_by_id(Instruction* currentInstruction)
     572{
     573    int resultVReg = currentInstruction[1].u.operand;
     574    int baseVReg = currentInstruction[2].u.operand;
     575    const Identifier* ident = &(m_codeBlock->identifier(currentInstruction[3].u.operand));
     576
    540577    emitGetVirtualRegister(baseVReg, regT0);
    541578   
     
    547584    JITGetByIdGenerator gen(
    548585        m_codeBlock, CodeOrigin(m_bytecodeOffset), CallSiteIndex(m_bytecodeOffset), RegisterSet::stubUnavailableRegisters(),
    549         JSValueRegs(regT0), JSValueRegs(regT0));
     586        JSValueRegs(regT0), JSValueRegs(regT0), AccessType::Get);
    550587    gen.generateFastPath(*this);
    551588    addSlowCase(gen.slowPathJump());
  • trunk/Source/JavaScriptCore/jit/JITPropertyAccess32_64.cpp

    r199108 r199170  
    283283    JITGetByIdGenerator gen(
    284284        m_codeBlock, CodeOrigin(m_bytecodeOffset), CallSiteIndex(currentInstruction), RegisterSet::stubUnavailableRegisters(),
    285         JSValueRegs::payloadOnly(regT0), JSValueRegs(regT1, regT0));
     285        JSValueRegs::payloadOnly(regT0), JSValueRegs(regT1, regT0), AccessType::Get);
    286286    gen.generateFastPath(*this);
    287287
     
    574574}
    575575
     576void JIT::emit_op_try_get_by_id(Instruction* currentInstruction)
     577{
     578    int dst = currentInstruction[1].u.operand;
     579    int base = currentInstruction[2].u.operand;
     580
     581    emitLoad(base, regT1, regT0);
     582    emitJumpSlowCaseIfNotJSCell(base, regT1);
     583
     584    JITGetByIdGenerator gen(
     585        m_codeBlock, CodeOrigin(m_bytecodeOffset), CallSiteIndex(currentInstruction), RegisterSet::stubUnavailableRegisters(),
     586        JSValueRegs::payloadOnly(regT0), JSValueRegs(regT1, regT0), AccessType::GetPure);
     587    gen.generateFastPath(*this);
     588    addSlowCase(gen.slowPathJump());
     589    m_getByIds.append(gen);
     590   
     591    emitStore(dst, regT1, regT0);
     592}
     593
     594void JIT::emitSlow_op_try_get_by_id(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
     595{
     596    int resultVReg = currentInstruction[1].u.operand;
     597    int baseVReg = currentInstruction[2].u.operand;
     598    const Identifier* ident = &(m_codeBlock->identifier(currentInstruction[3].u.operand));
     599
     600    linkSlowCaseIfNotJSCell(iter, baseVReg);
     601    linkSlowCase(iter);
     602
     603    JITGetByIdGenerator& gen = m_getByIds[m_getByIdIndex++];
     604
     605    Label coldPathBegin = label();
     606
     607    Call call = callOperation(operationTryGetByIdOptimize, resultVReg, gen.stubInfo(), regT1, regT0, ident->impl());
     608   
     609    gen.reportSlowPathCall(coldPathBegin, call);
     610}
     611
     612
    576613void JIT::emit_op_get_by_id(Instruction* currentInstruction)
    577614{
     
    588625    JITGetByIdGenerator gen(
    589626        m_codeBlock, CodeOrigin(m_bytecodeOffset), CallSiteIndex(currentInstruction), RegisterSet::stubUnavailableRegisters(),
    590         JSValueRegs::payloadOnly(regT0), JSValueRegs(regT1, regT0));
     627        JSValueRegs::payloadOnly(regT0), JSValueRegs(regT1, regT0), AccessType::Get);
    591628    gen.generateFastPath(*this);
    592629    addSlowCase(gen.slowPathJump());
  • trunk/Source/JavaScriptCore/jit/Repatch.cpp

    r199108 r199170  
    9494static void repatchByIdSelfAccess(
    9595    CodeBlock* codeBlock, StructureStubInfo& stubInfo, Structure* structure,
    96     PropertyOffset offset, const FunctionPtr &slowPathFunction,
     96    PropertyOffset offset, const FunctionPtr& slowPathFunction,
    9797    bool compact)
    9898{
     
    214214}
    215215
    216 static InlineCacheAction tryCacheGetByID(ExecState* exec, JSValue baseValue, const Identifier& propertyName, const PropertySlot& slot, StructureStubInfo& stubInfo)
     216inline J_JITOperation_ESsiJI appropriateOptimizingGetByIdFunction(GetByIDKind kind)
     217{
     218    if (kind == GetByIDKind::Normal)
     219        return operationGetByIdOptimize;
     220    return operationTryGetByIdOptimize;
     221}
     222
     223inline J_JITOperation_ESsiJI appropriateGenericGetByIdFunction(GetByIDKind kind)
     224{
     225    if (kind == GetByIDKind::Normal)
     226        return operationGetById;
     227    return operationTryGetById;
     228}
     229
     230static InlineCacheAction tryCacheGetByID(ExecState* exec, JSValue baseValue, const Identifier& propertyName, const PropertySlot& slot, StructureStubInfo& stubInfo, GetByIDKind kind)
    217231{
    218232    if (forceICFailure(exec))
     
    263277            && !loadTargetFromProxy) {
    264278            structure->startWatchingPropertyForReplacements(vm, slot.cachedOffset());
    265             repatchByIdSelfAccess(codeBlock, stubInfo, structure, slot.cachedOffset(), operationGetByIdOptimize, true);
     279            repatchByIdSelfAccess(codeBlock, stubInfo, structure, slot.cachedOffset(), appropriateOptimizingGetByIdFunction(kind), true);
    266280            stubInfo.initGetByIdSelf(codeBlock, structure, slot.cachedOffset());
    267281            return RetryCacheLater;
     
    296310            getter = jsDynamicCast<JSFunction*>(slot.getterSetter()->getter());
    297311
    298         if (!loadTargetFromProxy && getter && AccessCase::canEmitIntrinsicGetter(getter, structure))
     312        if (kind == GetByIDKind::Pure) {
     313            AccessCase::AccessType type;
     314            if (slot.isCacheableValue())
     315                type = AccessCase::Load;
     316            else if (slot.isUnset())
     317                type = AccessCase::Miss;
     318            else if (slot.isCacheableGetter())
     319                type = AccessCase::GetGetter;
     320            else
     321                RELEASE_ASSERT_NOT_REACHED();
     322
     323            newCase = AccessCase::tryGet(vm, codeBlock, type, offset, structure, conditionSet, loadTargetFromProxy, slot.watchpointSet());
     324        } else if (!loadTargetFromProxy && getter && AccessCase::canEmitIntrinsicGetter(getter, structure))
    299325            newCase = AccessCase::getIntrinsic(vm, codeBlock, getter, slot.cachedOffset(), structure, conditionSet);
    300326        else {
     
    331357}
    332358
    333 void repatchGetByID(ExecState* exec, JSValue baseValue, const Identifier& propertyName, const PropertySlot& slot, StructureStubInfo& stubInfo)
     359void repatchGetByID(ExecState* exec, JSValue baseValue, const Identifier& propertyName, const PropertySlot& slot, StructureStubInfo& stubInfo, GetByIDKind kind)
    334360{
    335361    GCSafeConcurrentJITLocker locker(exec->codeBlock()->m_lock, exec->vm().heap);
    336362   
    337     if (tryCacheGetByID(exec, baseValue, propertyName, slot, stubInfo) == GiveUpOnCache)
    338         repatchCall(exec->codeBlock(), stubInfo.callReturnLocation, operationGetById);
     363    if (tryCacheGetByID(exec, baseValue, propertyName, slot, stubInfo, kind) == GiveUpOnCache)
     364        repatchCall(exec->codeBlock(), stubInfo.callReturnLocation, appropriateGenericGetByIdFunction(kind));
    339365}
    340366
     
    911937}
    912938
    913 void resetGetByID(CodeBlock* codeBlock, StructureStubInfo& stubInfo)
    914 {
    915     repatchCall(codeBlock, stubInfo.callReturnLocation, operationGetByIdOptimize);
     939void resetGetByID(CodeBlock* codeBlock, StructureStubInfo& stubInfo, GetByIDKind kind)
     940{
     941    repatchCall(codeBlock, stubInfo.callReturnLocation, appropriateOptimizingGetByIdFunction(kind));
    916942    resetGetByIDCheckAndLoad(stubInfo);
    917943    MacroAssembler::repatchJump(stubInfo.callReturnLocation.jumpAtOffset(stubInfo.patch.deltaCallToJump), stubInfo.callReturnLocation.labelAtOffset(stubInfo.patch.deltaCallToSlowCase));
  • trunk/Source/JavaScriptCore/jit/Repatch.h

    r199108 r199170  
    3636namespace JSC {
    3737
    38 void repatchGetByID(ExecState*, JSValue, const Identifier&, const PropertySlot&, StructureStubInfo&);
     38enum class GetByIDKind {
     39    Normal,
     40    Pure
     41};
     42
     43void repatchGetByID(ExecState*, JSValue, const Identifier&, const PropertySlot&, StructureStubInfo&, GetByIDKind);
    3944void buildGetByIDList(ExecState*, JSValue, const Identifier&, const PropertySlot&, StructureStubInfo&);
    4045void buildGetByIDProtoList(ExecState*, JSValue, const Identifier&, const PropertySlot&, StructureStubInfo&);
     
    4752void linkVirtualFor(ExecState*, CallLinkInfo&);
    4853void linkPolymorphicCall(ExecState*, CallLinkInfo&, CallVariant);
    49 void resetGetByID(CodeBlock*, StructureStubInfo&);
     54void resetGetByID(CodeBlock*, StructureStubInfo&, GetByIDKind);
    5055void resetPutByID(CodeBlock*, StructureStubInfo&);
    5156void resetIn(CodeBlock*, StructureStubInfo&);
  • trunk/Source/JavaScriptCore/jsc.cpp

    r199164 r199170  
    2424
    2525#include "ArrayPrototype.h"
     26#include "BuiltinExecutableCreator.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"
     
    553555static EncodedJSValue JSC_HOST_CALL functionCreateImpureGetter(ExecState*);
    554556static EncodedJSValue JSC_HOST_CALL functionCreateCustomGetterObject(ExecState*);
     557static EncodedJSValue JSC_HOST_CALL functionCreateBuiltin(ExecState*);
    555558static EncodedJSValue JSC_HOST_CALL functionSetImpureGetterDelegate(ExecState*);
    556559
     
    573576static EncodedJSValue JSC_HOST_CALL functionHeapSize(ExecState*);
    574577static EncodedJSValue JSC_HOST_CALL functionAddressOf(ExecState*);
     578static EncodedJSValue JSC_HOST_CALL functionGetGetterSetter(ExecState*);
    575579#ifndef NDEBUG
    576580static EncodedJSValue JSC_HOST_CALL functionDumpCallFrame(ExecState*);
     
    744748        addFunction(vm, "gcHeapSize", functionHeapSize, 0);
    745749        addFunction(vm, "addressOf", functionAddressOf, 1);
     750        addFunction(vm, "getGetterSetter", functionGetGetterSetter, 2);
    746751#ifndef NDEBUG
    747752        addFunction(vm, "dumpCallFrame", functionDumpCallFrame, 0);
     
    793798        addFunction(vm, "createImpureGetter", functionCreateImpureGetter, 1);
    794799        addFunction(vm, "createCustomGetterObject", functionCreateCustomGetterObject, 0);
     800        addFunction(vm, "createBuiltin", functionCreateBuiltin, 2);
    795801        addFunction(vm, "setImpureGetterDelegate", functionSetImpureGetterDelegate, 2);
    796802
     
    13331339}
    13341340
     1341static EncodedJSValue JSC_HOST_CALL functionGetGetterSetter(ExecState* exec)
     1342{
     1343    JSValue value = exec->argument(0);
     1344    if (!value.isObject())
     1345        return JSValue::encode(jsUndefined());
     1346
     1347    JSValue property = exec->argument(1);
     1348    if (!property.isString())
     1349        return JSValue::encode(jsUndefined());
     1350
     1351    Identifier ident = Identifier::fromString(&exec->vm(), property.toString(exec)->value(exec));
     1352
     1353    PropertySlot slot(value, PropertySlot::InternalMethodType::VMInquiry);
     1354    value.getPropertySlot(exec, ident, slot);
     1355
     1356    JSValue result;
     1357    if (slot.isCacheableGetter())
     1358        result = slot.getterSetter();
     1359    else
     1360        result = jsNull();
     1361
     1362    return JSValue::encode(result);
     1363}
     1364
    13351365EncodedJSValue JSC_HOST_CALL functionVersion(ExecState*)
    13361366{
     
    17201750        return JSValue::encode(exec->vm().throwException(exec, error));
    17211751    return JSValue::encode(jsUndefined());
     1752}
     1753
     1754EncodedJSValue JSC_HOST_CALL functionCreateBuiltin(ExecState* exec)
     1755{
     1756    if (exec->argumentCount() < 1 || !exec->argument(0).isString())
     1757        return JSValue::encode(jsUndefined());
     1758
     1759    String functionText = exec->argument(0).toString(exec)->value(exec);
     1760    if (exec->hadException())
     1761        return JSValue::encode(JSValue());
     1762
     1763    VM& vm = exec->vm();
     1764    const SourceCode& source = makeSource(functionText);
     1765    JSFunction* func = JSFunction::createBuiltinFunction(vm, createBuiltinExecutable(vm, source, Identifier::fromString(&vm, "foo"), ConstructorKind::None, ConstructAbility::CannotConstruct)->link(vm, source), exec->lexicalGlobalObject());
     1766
     1767    return JSValue::encode(func);
    17221768}
    17231769
  • trunk/Source/JavaScriptCore/llint/LLIntData.cpp

    r199108 r199170  
    145145    STATIC_ASSERT(StringType == 6);
    146146    STATIC_ASSERT(SymbolType == 7);
    147     STATIC_ASSERT(ObjectType == 21);
    148     STATIC_ASSERT(FinalObjectType == 22);
    149     STATIC_ASSERT(JSFunctionType == 24);
     147    STATIC_ASSERT(ObjectType == 20);
     148    STATIC_ASSERT(FinalObjectType == 21);
     149    STATIC_ASSERT(JSFunctionType == 23);
    150150    STATIC_ASSERT(MasqueradesAsUndefined == 1);
    151151    STATIC_ASSERT(ImplementsDefaultHasInstance == 2);
  • trunk/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp

    r199108 r199170  
    546546}
    547547
     548LLINT_SLOW_PATH_DECL(slow_path_try_get_by_id)
     549{
     550    LLINT_BEGIN();
     551    CodeBlock* codeBlock = exec->codeBlock();
     552    const Identifier& ident = codeBlock->identifier(pc[3].u.operand);
     553    JSValue baseValue = LLINT_OP_C(2).jsValue();
     554    PropertySlot slot(baseValue, PropertySlot::PropertySlot::InternalMethodType::VMInquiry);
     555
     556    baseValue.getPropertySlot(exec, ident, slot);
     557
     558    LLINT_RETURN(slot.getPureResult());
     559}
     560
    548561LLINT_SLOW_PATH_DECL(slow_path_get_by_id)
    549562{
  • trunk/Source/JavaScriptCore/llint/LLIntSlowPaths.h

    r199108 r199170  
    7070LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_instanceof);
    7171LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_instanceof_custom);
     72LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_try_get_by_id);
    7273LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_get_by_id);
    7374LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_get_arguments_length);
  • trunk/Source/JavaScriptCore/llint/LowLevelInterpreter.asm

    r199108 r199170  
    327327const StringType = 6
    328328const SymbolType = 7
    329 const ObjectType = 21
    330 const FinalObjectType = 22
    331 const JSFunctionType = 24
     329const ObjectType = 20
     330const FinalObjectType = 21
     331const JSFunctionType = 23
    332332
    333333# Type flags constants.
     
    13021302
    13031303
     1304_llint_op_try_get_by_id:
     1305    traceExecution()
     1306    callSlowPath(_llint_slow_path_try_get_by_id)
     1307    dispatch(4)
     1308
     1309
    13041310_llint_op_del_by_id:
    13051311    traceExecution()
  • trunk/Source/JavaScriptCore/runtime/GetterSetter.cpp

    r199108 r199170  
    3434STATIC_ASSERT_IS_TRIVIALLY_DESTRUCTIBLE(GetterSetter);
    3535
    36 const ClassInfo GetterSetter::s_info = { "GetterSetter", 0, 0, CREATE_METHOD_TABLE(GetterSetter) };
     36const ClassInfo GetterSetter::s_info = { "GetterSetter", &Base::s_info, 0, CREATE_METHOD_TABLE(GetterSetter) };
    3737
    3838void GetterSetter::visitChildren(JSCell* cell, SlotVisitor& visitor)
  • trunk/Source/JavaScriptCore/runtime/GetterSetter.h

    r199108 r199170  
    4242// that constant is observed to have a non-null setter (or getter) then we can
    4343// constant fold that setter (or getter).
    44 class GetterSetter final : public JSCell {
     44class GetterSetter final : public JSNonFinalObject {
    4545    friend class JIT;
    46 
     46    typedef JSNonFinalObject Base;
    4747private:
    4848    GetterSetter(VM& vm, JSGlobalObject* globalObject)
    49         : JSCell(vm, vm.getterSetterStructure.get())
     49        : Base(vm, vm.getterSetterStructure.get())
    5050    {
    5151        m_getter.set(vm, this, globalObject->nullGetterFunction());
     
    5454
    5555public:
    56     typedef JSCell Base;
    57     static const unsigned StructureFlags = Base::StructureFlags | StructureIsImmortal;
     56
     57    static const unsigned StructureFlags = Base::StructureFlags | OverridesGetOwnPropertySlot | StructureIsImmortal;
    5858
    5959    static GetterSetter* create(VM& vm, JSGlobalObject* globalObject)
     
    129129    }
    130130
    131     DECLARE_INFO;
     131    DECLARE_EXPORT_INFO;
     132
     133    static bool getOwnPropertySlot(JSObject*, ExecState*, PropertyName, PropertySlot&) { RELEASE_ASSERT_NOT_REACHED(); return false; }
     134    static bool put(JSCell*, ExecState*, PropertyName, JSValue, PutPropertySlot&) { RELEASE_ASSERT_NOT_REACHED(); return false; }
     135    static bool defineOwnProperty(JSObject*, ExecState*, PropertyName, const PropertyDescriptor&, bool) { RELEASE_ASSERT_NOT_REACHED(); return false; }
     136    static bool deleteProperty(JSCell*, ExecState*, PropertyName) { RELEASE_ASSERT_NOT_REACHED(); return false; }
    132137
    133138private:
  • trunk/Source/JavaScriptCore/runtime/JSType.h

    r199164 r199170  
    3636    SymbolType,
    3737
    38     GetterSetterType,
    3938    CustomGetterSetterType,
    4039    APIValueWrapperType,
     
    7675    DataViewType,
    7776
     77    GetterSetterType,
    7878    GlobalObjectType,
    7979    LexicalEnvironmentType,
  • trunk/Source/JavaScriptCore/runtime/PropertySlot.cpp

    r199108 r199170  
    4040}
    4141
     42JSValue PropertySlot::getPureResult() const
     43{
     44    JSValue result;
     45    if (isTaintedByProxy())
     46        result = jsNull();
     47    else if (isCacheableValue())
     48        result = JSValue::decode(m_data.value);
     49    else if (isCacheableGetter())
     50        result = getterSetter();
     51    else if (isUnset())
     52        result = jsUndefined();
     53    else
     54        result = jsNull();
     55   
     56    return result;
     57}
     58
    4259} // namespace JSC
  • trunk/Source/JavaScriptCore/runtime/PropertySlot.h

    r199108 r199170  
    9595    JSValue getValue(ExecState*, PropertyName) const;
    9696    JSValue getValue(ExecState*, unsigned propertyName) const;
     97    JSValue getPureResult() const;
    9798
    9899    bool isCacheable() const { return m_cacheability == CachingAllowed && m_offset != invalidOffset; }
  • trunk/Source/JavaScriptCore/runtime/ProxyObject.cpp

    r199108 r199170  
    333333{
    334334    slot.disableCaching();
    335     if (slot.internalMethodType() != PropertySlot::InternalMethodType::VMInquiry)
    336         slot.setIsTaintedByProxy();
     335    slot.setIsTaintedByProxy();
    337336    switch (slot.internalMethodType()) {
    338337    case PropertySlot::InternalMethodType::Get:
Note: See TracChangeset for help on using the changeset viewer.