Title: [199104] trunk/Source/_javascript_Core
Revision
199104
Author
keith_mil...@apple.com
Date
2016-04-06 10:36:12 -0700 (Wed, 06 Apr 2016)

Log 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.

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

Modified Paths

Added Paths

Diff

Modified: trunk/Source/_javascript_Core/ChangeLog (199103 => 199104)


--- trunk/Source/_javascript_Core/ChangeLog	2016-04-06 17:33:57 UTC (rev 199103)
+++ trunk/Source/_javascript_Core/ChangeLog	2016-04-06 17:36:12 UTC (rev 199104)
@@ -1,3 +1,124 @@
+2016-04-06  Keith Miller  <keith_mil...@apple.com>
+
+        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.
+
+        * 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):
+
 2016-04-05  Chris Dumez  <cdu...@apple.com>
 
         Add support for [EnabledAtRuntime] operations on DOMWindow

Modified: trunk/Source/_javascript_Core/builtins/BuiltinExecutables.cpp (199103 => 199104)


--- trunk/Source/_javascript_Core/builtins/BuiltinExecutables.cpp	2016-04-06 17:33:57 UTC (rev 199103)
+++ trunk/Source/_javascript_Core/builtins/BuiltinExecutables.cpp	2016-04-06 17:36:12 UTC (rev 199104)
@@ -35,8 +35,6 @@
 
 namespace JSC {
 
-static UnlinkedFunctionExecutable* createExecutableInternal(VM&, const SourceCode&, const Identifier&, ConstructorKind, ConstructAbility);
-
 BuiltinExecutables::BuiltinExecutables(VM& vm)
     : m_vm(vm)
 #define INITIALIZE_BUILTIN_SOURCE_MEMBERS(name, functionName, length) , m_##name##Source(makeSource(StringImpl::createFromLiteral(s_##name, length)))
@@ -54,9 +52,9 @@
     case ConstructorKind::None:
         break;
     case ConstructorKind::Base:
-        return createExecutableInternal(m_vm, makeSource(baseConstructorCode), name, constructorKind, ConstructAbility::CanConstruct);
+        return createExecutable(m_vm, makeSource(baseConstructorCode), name, constructorKind, ConstructAbility::CanConstruct);
     case ConstructorKind::Derived:
-        return createExecutableInternal(m_vm, makeSource(derivedConstructorCode), name, constructorKind, ConstructAbility::CanConstruct);
+        return createExecutable(m_vm, makeSource(derivedConstructorCode), name, constructorKind, ConstructAbility::CanConstruct);
     }
     ASSERT_NOT_REACHED();
     return nullptr;
@@ -64,15 +62,15 @@
 
 UnlinkedFunctionExecutable* BuiltinExecutables::createBuiltinExecutable(const SourceCode& code, const Identifier& name, ConstructAbility constructAbility)
 {
-    return createExecutableInternal(m_vm, code, name, ConstructorKind::None, constructAbility);
+    return createExecutable(m_vm, code, name, ConstructorKind::None, constructAbility);
 }
 
 UnlinkedFunctionExecutable* createBuiltinExecutable(VM& vm, const SourceCode& code, const Identifier& name, ConstructAbility constructAbility)
 {
-    return createExecutableInternal(vm, code, name, ConstructorKind::None, constructAbility);
+    return BuiltinExecutables::createExecutable(vm, code, name, ConstructorKind::None, constructAbility);
 }
 
-UnlinkedFunctionExecutable* createExecutableInternal(VM& vm, const SourceCode& source, const Identifier& name, ConstructorKind constructorKind, ConstructAbility constructAbility)
+UnlinkedFunctionExecutable* BuiltinExecutables::createExecutable(VM& vm, const SourceCode& source, const Identifier& name, ConstructorKind constructorKind, ConstructAbility constructAbility)
 {
     JSTextPosition positionBeforeLastNewline;
     ParserError error;

Modified: trunk/Source/_javascript_Core/builtins/BuiltinExecutables.h (199103 => 199104)


--- trunk/Source/_javascript_Core/builtins/BuiltinExecutables.h	2016-04-06 17:33:57 UTC (rev 199103)
+++ trunk/Source/_javascript_Core/builtins/BuiltinExecutables.h	2016-04-06 17:36:12 UTC (rev 199104)
@@ -52,6 +52,7 @@
 
     UnlinkedFunctionExecutable* createDefaultConstructor(ConstructorKind, const Identifier& name);
 
+    JS_EXPORT_PRIVATE static UnlinkedFunctionExecutable* createExecutable(VM&, const SourceCode&, const Identifier&, ConstructorKind, ConstructAbility);
 private:
     void finalize(Handle<Unknown>, void* context) override;
 

Modified: trunk/Source/_javascript_Core/bytecode/BytecodeIntrinsicRegistry.h (199103 => 199104)


--- trunk/Source/_javascript_Core/bytecode/BytecodeIntrinsicRegistry.h	2016-04-06 17:33:57 UTC (rev 199103)
+++ trunk/Source/_javascript_Core/bytecode/BytecodeIntrinsicRegistry.h	2016-04-06 17:36:12 UTC (rev 199104)
@@ -41,6 +41,7 @@
 #define JSC_COMMON_BYTECODE_INTRINSIC_FUNCTIONS_EACH_NAME(macro) \
     macro(assert) \
     macro(isObject) \
+    macro(tryGetById) \
     macro(putByValDirect) \
     macro(toString)
 

Modified: trunk/Source/_javascript_Core/bytecode/BytecodeList.json (199103 => 199104)


--- trunk/Source/_javascript_Core/bytecode/BytecodeList.json	2016-04-06 17:33:57 UTC (rev 199103)
+++ trunk/Source/_javascript_Core/bytecode/BytecodeList.json	2016-04-06 17:36:12 UTC (rev 199104)
@@ -57,6 +57,7 @@
             { "name" : "op_is_object_or_null", "length" : 3 },
             { "name" : "op_is_function", "length" : 3 },
             { "name" : "op_in", "length" : 4 },
+            { "name" : "op_try_get_by_id", "length" : 4 },
             { "name" : "op_get_by_id", "length" : 9  },
             { "name" : "op_get_array_length", "length" : 9 },
             { "name" : "op_put_by_id", "length" : 9 },

Modified: trunk/Source/_javascript_Core/bytecode/BytecodeUseDef.h (199103 => 199104)


--- trunk/Source/_javascript_Core/bytecode/BytecodeUseDef.h	2016-04-06 17:33:57 UTC (rev 199103)
+++ trunk/Source/_javascript_Core/bytecode/BytecodeUseDef.h	2016-04-06 17:36:12 UTC (rev 199104)
@@ -143,6 +143,7 @@
     case op_resolve_scope:
     case op_get_from_scope:
     case op_to_primitive:
+    case op_try_get_by_id:
     case op_get_by_id:
     case op_get_array_length:
     case op_typeof:
@@ -367,6 +368,7 @@
     case op_tail_call:
     case op_call_eval:
     case op_construct:
+    case op_try_get_by_id:
     case op_get_by_id:
     case op_get_array_length:
     case op_overrides_has_instance:

Modified: trunk/Source/_javascript_Core/bytecode/CodeBlock.cpp (199103 => 199104)


--- trunk/Source/_javascript_Core/bytecode/CodeBlock.cpp	2016-04-06 17:33:57 UTC (rev 199103)
+++ trunk/Source/_javascript_Core/bytecode/CodeBlock.cpp	2016-04-06 17:36:12 UTC (rev 199104)
@@ -1095,6 +1095,14 @@
             printBinaryOp(out, exec, location, it, "in");
             break;
         }
+        case op_try_get_by_id: {
+            int r0 = (++it)->u.operand;
+            int r1 = (++it)->u.operand;
+            int id0 = (++it)->u.operand;
+            printLocationAndOp(out, exec, location, it, "try_get_by_id");
+            out.printf("%s, %s, %s", registerName(r0).data(), registerName(r1).data(), idName(id0, identifier(id0)).data());
+            break;
+        }
         case op_get_by_id:
         case op_get_array_length: {
             printGetByIdOp(out, exec, location, it);

Modified: trunk/Source/_javascript_Core/bytecode/PolymorphicAccess.cpp (199103 => 199104)


--- trunk/Source/_javascript_Core/bytecode/PolymorphicAccess.cpp	2016-04-06 17:33:57 UTC (rev 199103)
+++ trunk/Source/_javascript_Core/bytecode/PolymorphicAccess.cpp	2016-04-06 17:36:12 UTC (rev 199104)
@@ -159,6 +159,26 @@
 {
 }
 
+std::unique_ptr<AccessCase> AccessCase::tryGet(
+    VM& vm, JSCell* owner, AccessType type, PropertyOffset offset, Structure* structure,
+    const ObjectPropertyConditionSet& conditionSet, bool viaProxy, WatchpointSet* additionalSet)
+{
+    std::unique_ptr<AccessCase> result(new AccessCase());
+
+    result->m_type = type;
+    result->m_offset = offset;
+    result->m_structure.set(vm, owner, structure);
+    result->m_conditionSet = conditionSet;
+
+    if (viaProxy || additionalSet) {
+        result->m_rareData = std::make_unique<RareData>();
+        result->m_rareData->viaProxy = viaProxy;
+        result->m_rareData->additionalSet = additionalSet;
+    }
+
+    return result;
+}
+
 std::unique_ptr<AccessCase> AccessCase::get(
     VM& vm, JSCell* owner, AccessType type, PropertyOffset offset, Structure* structure,
     const ObjectPropertyConditionSet& conditionSet, bool viaProxy, WatchpointSet* additionalSet,
@@ -685,6 +705,7 @@
         return;
 
     case Load:
+    case GetGetter:
     case Getter:
     case Setter:
     case CustomValueGetter:
@@ -720,7 +741,7 @@
 
         GPRReg loadedValueGPR = InvalidGPRReg;
         if (m_type != CustomValueGetter && m_type != CustomAccessorGetter && m_type != CustomValueSetter && m_type != CustomAccessorSetter) {
-            if (m_type == Load)
+            if (m_type == Load || m_type == GetGetter)
                 loadedValueGPR = valueRegs.payloadGPR();
             else
                 loadedValueGPR = scratchGPR;
@@ -739,7 +760,7 @@
             jit.load64(
                 CCallHelpers::Address(storageGPR, offsetRelativeToBase(m_offset)), loadedValueGPR);
 #else
-            if (m_type == Load) {
+            if (m_type == Load || m_type == GetGetter) {
                 jit.load32(
                     CCallHelpers::Address(storageGPR, offsetRelativeToBase(m_offset) + TagOffset),
                     valueRegs.tagGPR());
@@ -750,7 +771,7 @@
 #endif
         }
 
-        if (m_type == Load) {
+        if (m_type == Load || m_type == GetGetter) {
             state.succeed();
             return;
         }
@@ -1621,6 +1642,9 @@
     case AccessCase::Miss:
         out.print("Miss");
         return;
+    case AccessCase::GetGetter:
+        out.print("GetGetter");
+        return;
     case AccessCase::Getter:
         out.print("Getter");
         return;

Modified: trunk/Source/_javascript_Core/bytecode/PolymorphicAccess.h (199103 => 199104)


--- trunk/Source/_javascript_Core/bytecode/PolymorphicAccess.h	2016-04-06 17:33:57 UTC (rev 199103)
+++ trunk/Source/_javascript_Core/bytecode/PolymorphicAccess.h	2016-04-06 17:36:12 UTC (rev 199104)
@@ -57,6 +57,7 @@
         Transition,
         Replace,
         Miss,
+        GetGetter,
         Getter,
         Setter,
         CustomValueGetter,
@@ -70,78 +71,12 @@
         StringLength
     };
 
-    static bool isGet(AccessType type)
-    {
-        switch (type) {
-        case Transition:
-        case Replace:
-        case Setter:
-        case CustomValueSetter:
-        case CustomAccessorSetter:
-        case InHit:
-        case InMiss:
-            return false;
-        case Load:
-        case MegamorphicLoad:
-        case Miss:
-        case Getter:
-        case CustomValueGetter:
-        case CustomAccessorGetter:
-        case IntrinsicGetter:
-        case ArrayLength:
-        case StringLength:
-            return true;
-        }
-    }
+    static std::unique_ptr<AccessCase> tryGet(
+        VM&, JSCell* owner, AccessType, PropertyOffset, Structure*,
+        const ObjectPropertyConditionSet& = ObjectPropertyConditionSet(),
+        bool viaProxy = false,
+        WatchpointSet* additionalSet = nullptr);
 
-    static bool isPut(AccessType type)
-    {
-        switch (type) {
-        case Load:
-        case MegamorphicLoad:
-        case Miss:
-        case Getter:
-        case CustomValueGetter:
-        case CustomAccessorGetter:
-        case IntrinsicGetter:
-        case InHit:
-        case InMiss:
-        case ArrayLength:
-        case StringLength:
-            return false;
-        case Transition:
-        case Replace:
-        case Setter:
-        case CustomValueSetter:
-        case CustomAccessorSetter:
-            return true;
-        }
-    }
-
-    static bool isIn(AccessType type)
-    {
-        switch (type) {
-        case Load:
-        case MegamorphicLoad:
-        case Miss:
-        case Getter:
-        case CustomValueGetter:
-        case CustomAccessorGetter:
-        case IntrinsicGetter:
-        case Transition:
-        case Replace:
-        case Setter:
-        case CustomValueSetter:
-        case CustomAccessorSetter:
-        case ArrayLength:
-        case StringLength:
-            return false;
-        case InHit:
-        case InMiss:
-            return true;
-        }
-    }
-
     static std::unique_ptr<AccessCase> get(
         VM&, JSCell* owner, AccessType, PropertyOffset, Structure*,
         const ObjectPropertyConditionSet& = ObjectPropertyConditionSet(),

Modified: trunk/Source/_javascript_Core/bytecode/StructureStubInfo.cpp (199103 => 199104)


--- trunk/Source/_javascript_Core/bytecode/StructureStubInfo.cpp	2016-04-06 17:33:57 UTC (rev 199103)
+++ trunk/Source/_javascript_Core/bytecode/StructureStubInfo.cpp	2016-04-06 17:36:12 UTC (rev 199104)
@@ -148,8 +148,11 @@
     }
 
     switch (accessType) {
+    case AccessType::GetPure:
+        resetGetByID(codeBlock, *this, GetByIDKind::Pure);
+        break;
     case AccessType::Get:
-        resetGetByID(codeBlock, *this);
+        resetGetByID(codeBlock, *this, GetByIDKind::Normal);
         break;
     case AccessType::Put:
         resetPutByID(codeBlock, *this);

Modified: trunk/Source/_javascript_Core/bytecode/StructureStubInfo.h (199103 => 199104)


--- trunk/Source/_javascript_Core/bytecode/StructureStubInfo.h	2016-04-06 17:33:57 UTC (rev 199103)
+++ trunk/Source/_javascript_Core/bytecode/StructureStubInfo.h	2016-04-06 17:36:12 UTC (rev 199104)
@@ -47,6 +47,7 @@
 
 enum class AccessType : int8_t {
     Get,
+    GetPure,
     Put,
     In
 };

Modified: trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.cpp (199103 => 199104)


--- trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.cpp	2016-04-06 17:33:57 UTC (rev 199103)
+++ trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.cpp	2016-04-06 17:36:12 UTC (rev 199104)
@@ -2360,6 +2360,17 @@
     return dst;
 }
 
+RegisterID* BytecodeGenerator::emitTryGetById(RegisterID* dst, RegisterID* base, const Identifier& property)
+{
+    ASSERT_WITH_MESSAGE(!parseIndex(property), "Indexed properties are not supported with tryGetById.");
+
+    emitOpcode(op_try_get_by_id);
+    instructions().append(kill(dst));
+    instructions().append(base->index());
+    instructions().append(addConstant(property));
+    return dst;
+}
+
 RegisterID* BytecodeGenerator::emitGetById(RegisterID* dst, RegisterID* base, const Identifier& property)
 {
     ASSERT_WITH_MESSAGE(!parseIndex(property), "Indexed properties should be handled with get_by_val.");

Modified: trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.h (199103 => 199104)


--- trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.h	2016-04-06 17:33:57 UTC (rev 199103)
+++ trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.h	2016-04-06 17:36:12 UTC (rev 199104)
@@ -540,6 +540,7 @@
         RegisterID* emitTypeOf(RegisterID* dst, RegisterID* src) { return emitUnaryOp(op_typeof, dst, src); }
         RegisterID* emitIn(RegisterID* dst, RegisterID* property, RegisterID* base) { return emitBinaryOp(op_in, dst, property, base, OperandTypes()); }
 
+        RegisterID* emitTryGetById(RegisterID* dst, RegisterID* base, const Identifier& property);
         RegisterID* emitGetById(RegisterID* dst, RegisterID* base, const Identifier& property);
         RegisterID* emitPutById(RegisterID* base, const Identifier& property, RegisterID* value);
         RegisterID* emitDirectPutById(RegisterID* base, const Identifier& property, RegisterID* value, PropertyNode::PutType);

Modified: trunk/Source/_javascript_Core/bytecompiler/NodesCodegen.cpp (199103 => 199104)


--- trunk/Source/_javascript_Core/bytecompiler/NodesCodegen.cpp	2016-04-06 17:33:57 UTC (rev 199103)
+++ trunk/Source/_javascript_Core/bytecompiler/NodesCodegen.cpp	2016-04-06 17:36:12 UTC (rev 199104)
@@ -842,6 +842,21 @@
     return generator.moveToDestinationIfNeeded(dst, generator.emitDirectPutByVal(base.get(), index.get(), value.get()));
 }
 
+RegisterID* BytecodeIntrinsicNode::emit_intrinsic_tryGetById(BytecodeGenerator& generator, RegisterID* dst)
+{
+    ArgumentListNode* node = m_args->m_listNode;
+    RefPtr<RegisterID> base = generator.emitNode(node);
+    node = node->m_next;
+
+    // Since this is a builtin we expect the creator to use a string literal as the second argument.
+    ASSERT(node->m_expr->isString());
+    const Identifier& ident = static_cast<StringNode*>(node->m_expr)->value();
+    ASSERT(!node->m_next);
+
+    RegisterID* finalDest = generator.finalDestination(dst);
+    return generator.emitTryGetById(finalDest, base.get(), ident);
+}
+
 RegisterID* BytecodeIntrinsicNode::emit_intrinsic_toString(BytecodeGenerator& generator, RegisterID* dst)
 {
     ArgumentListNode* node = m_args->m_listNode;

Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp (199103 => 199104)


--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp	2016-04-06 17:33:57 UTC (rev 199103)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp	2016-04-06 17:36:12 UTC (rev 199104)
@@ -194,7 +194,7 @@
     JITGetByIdGenerator gen(
         m_jit.codeBlock(), codeOrigin, callSite, usedRegisters,
         JSValueRegs(baseTagGPROrNone, basePayloadGPR),
-        JSValueRegs(resultTagGPR, resultPayloadGPR));
+        JSValueRegs(resultTagGPR, resultPayloadGPR), AccessType::Get);
     
     gen.generateFastPath(m_jit);
     

Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp (199103 => 199104)


--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp	2016-04-06 17:33:57 UTC (rev 199103)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp	2016-04-06 17:36:12 UTC (rev 199104)
@@ -164,7 +164,7 @@
     }
     JITGetByIdGenerator gen(
         m_jit.codeBlock(), codeOrigin, callSite, usedRegisters, JSValueRegs(baseGPR),
-        JSValueRegs(resultGPR));
+        JSValueRegs(resultGPR), AccessType::Get);
     gen.generateFastPath(m_jit);
     
     JITCompiler::JumpList slowCases;

Modified: trunk/Source/_javascript_Core/ftl/FTLLowerDFGToB3.cpp (199103 => 199104)


--- trunk/Source/_javascript_Core/ftl/FTLLowerDFGToB3.cpp	2016-04-06 17:33:57 UTC (rev 199103)
+++ trunk/Source/_javascript_Core/ftl/FTLLowerDFGToB3.cpp	2016-04-06 17:36:12 UTC (rev 199104)
@@ -7331,7 +7331,7 @@
                 auto generator = Box<JITGetByIdGenerator>::create(
                     jit.codeBlock(), node->origin.semantic, callSiteIndex,
                     params.unavailableRegisters(), JSValueRegs(params[1].gpr()),
-                    JSValueRegs(params[0].gpr()));
+                    JSValueRegs(params[0].gpr()), AccessType::Get);
 
                 generator->generateFastPath(jit);
                 CCallHelpers::Label done = jit.label();

Modified: trunk/Source/_javascript_Core/jit/JIT.cpp (199103 => 199104)


--- trunk/Source/_javascript_Core/jit/JIT.cpp	2016-04-06 17:33:57 UTC (rev 199103)
+++ trunk/Source/_javascript_Core/jit/JIT.cpp	2016-04-06 17:36:12 UTC (rev 199104)
@@ -228,6 +228,7 @@
         DEFINE_OP(op_get_scope)
         DEFINE_OP(op_eq)
         DEFINE_OP(op_eq_null)
+        DEFINE_OP(op_try_get_by_id)
         case op_get_array_length:
         DEFINE_OP(op_get_by_id)
         DEFINE_OP(op_get_by_val)
@@ -406,6 +407,7 @@
         DEFINE_SLOWCASE_OP(op_create_this)
         DEFINE_SLOWCASE_OP(op_div)
         DEFINE_SLOWCASE_OP(op_eq)
+        DEFINE_SLOWCASE_OP(op_try_get_by_id)
         case op_get_array_length:
         DEFINE_SLOWCASE_OP(op_get_by_id)
         DEFINE_SLOWCASE_OP(op_get_by_val)

Modified: trunk/Source/_javascript_Core/jit/JIT.h (199103 => 199104)


--- trunk/Source/_javascript_Core/jit/JIT.h	2016-04-06 17:33:57 UTC (rev 199103)
+++ trunk/Source/_javascript_Core/jit/JIT.h	2016-04-06 17:36:12 UTC (rev 199104)
@@ -502,6 +502,7 @@
         void emit_op_get_scope(Instruction*);
         void emit_op_eq(Instruction*);
         void emit_op_eq_null(Instruction*);
+        void emit_op_try_get_by_id(Instruction*);
         void emit_op_get_by_id(Instruction*);
         void emit_op_get_arguments_length(Instruction*);
         void emit_op_get_by_val(Instruction*);
@@ -614,6 +615,7 @@
         void emitSlow_op_div(Instruction*, Vector<SlowCaseEntry>::iterator&);
         void emitSlow_op_eq(Instruction*, Vector<SlowCaseEntry>::iterator&);
         void emitSlow_op_get_callee(Instruction*, Vector<SlowCaseEntry>::iterator&);
+        void emitSlow_op_try_get_by_id(Instruction*, Vector<SlowCaseEntry>::iterator&);
         void emitSlow_op_get_by_id(Instruction*, Vector<SlowCaseEntry>::iterator&);
         void emitSlow_op_get_arguments_length(Instruction*, Vector<SlowCaseEntry>::iterator&);
         void emitSlow_op_get_by_val(Instruction*, Vector<SlowCaseEntry>::iterator&);
@@ -738,8 +740,10 @@
         MacroAssembler::Call callOperation(V_JITOperation_EC, JSCell*);
         MacroAssembler::Call callOperation(J_JITOperation_EJ, int, GPRReg);
 #if USE(JSVALUE64)
+        MacroAssembler::Call callOperation(J_JITOperation_ESsiJI, int, StructureStubInfo*, GPRReg, UniquedStringImpl*);
         MacroAssembler::Call callOperation(WithProfileTag, J_JITOperation_ESsiJI, int, StructureStubInfo*, GPRReg, UniquedStringImpl*);
 #else
+        MacroAssembler::Call callOperation(J_JITOperation_ESsiJI, int, StructureStubInfo*, GPRReg, GPRReg, UniquedStringImpl*);
         MacroAssembler::Call callOperation(WithProfileTag, J_JITOperation_ESsiJI, int, StructureStubInfo*, GPRReg, GPRReg, UniquedStringImpl*);
 #endif
         MacroAssembler::Call callOperation(J_JITOperation_EJIdc, int, GPRReg, const Identifier*);

Modified: trunk/Source/_javascript_Core/jit/JITInlineCacheGenerator.cpp (199103 => 199104)


--- trunk/Source/_javascript_Core/jit/JITInlineCacheGenerator.cpp	2016-04-06 17:33:57 UTC (rev 199103)
+++ trunk/Source/_javascript_Core/jit/JITInlineCacheGenerator.cpp	2016-04-06 17:36:12 UTC (rev 199104)
@@ -104,9 +104,9 @@
 
 JITGetByIdGenerator::JITGetByIdGenerator(
     CodeBlock* codeBlock, CodeOrigin codeOrigin, CallSiteIndex callSite, const RegisterSet& usedRegisters,
-    JSValueRegs base, JSValueRegs value)
+    JSValueRegs base, JSValueRegs value, AccessType accessType)
     : JITByIdGenerator(
-        codeBlock, codeOrigin, callSite, AccessType::Get, usedRegisters, base, value)
+        codeBlock, codeOrigin, callSite, accessType, usedRegisters, base, value)
 {
     RELEASE_ASSERT(base.payloadGPR() != value.tagGPR());
 }

Modified: trunk/Source/_javascript_Core/jit/JITInlineCacheGenerator.h (199103 => 199104)


--- trunk/Source/_javascript_Core/jit/JITInlineCacheGenerator.h	2016-04-06 17:33:57 UTC (rev 199103)
+++ trunk/Source/_javascript_Core/jit/JITInlineCacheGenerator.h	2016-04-06 17:36:12 UTC (rev 199104)
@@ -96,7 +96,7 @@
 
     JITGetByIdGenerator(
         CodeBlock*, CodeOrigin, CallSiteIndex, const RegisterSet& usedRegisters, JSValueRegs base,
-        JSValueRegs value);
+        JSValueRegs value, AccessType);
     
     void generateFastPath(MacroAssembler&);
 };

Modified: trunk/Source/_javascript_Core/jit/JITInlines.h (199103 => 199104)


--- trunk/Source/_javascript_Core/jit/JITInlines.h	2016-04-06 17:33:57 UTC (rev 199103)
+++ trunk/Source/_javascript_Core/jit/JITInlines.h	2016-04-06 17:36:12 UTC (rev 199104)
@@ -459,6 +459,12 @@
     return appendCallWithExceptionCheck(operation);
 }
 
+ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(J_JITOperation_ESsiJI operation, int dst, StructureStubInfo* stubInfo, GPRReg arg1, UniquedStringImpl* uid)
+{
+    setupArgumentsWithExecState(TrustedImmPtr(stubInfo), arg1, TrustedImmPtr(uid));
+    return appendCallWithExceptionCheckSetJSValueResult(operation, dst);
+}
+
 ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(JIT::WithProfileTag, J_JITOperation_ESsiJI operation, int dst, StructureStubInfo* stubInfo, GPRReg arg1, UniquedStringImpl* uid)
 {
     setupArgumentsWithExecState(TrustedImmPtr(stubInfo), arg1, TrustedImmPtr(uid));
@@ -642,6 +648,12 @@
     return appendCallWithExceptionCheckSetJSValueResult(operation, dst);
 }
 
+ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(J_JITOperation_ESsiJI operation, int dst, StructureStubInfo* stubInfo, GPRReg arg1Tag, GPRReg arg1Payload, UniquedStringImpl* uid)
+{
+    setupArgumentsWithExecState(TrustedImmPtr(stubInfo), arg1Payload, arg1Tag, TrustedImmPtr(uid));
+    return appendCallWithExceptionCheckSetJSValueResult(operation, dst);
+}
+
 ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(JIT::WithProfileTag, J_JITOperation_ESsiJI operation, int dst, StructureStubInfo* stubInfo, GPRReg arg1Tag, GPRReg arg1Payload, UniquedStringImpl* uid)
 {
     setupArgumentsWithExecState(TrustedImmPtr(stubInfo), arg1Payload, arg1Tag, TrustedImmPtr(uid));

Modified: trunk/Source/_javascript_Core/jit/JITOperations.cpp (199103 => 199104)


--- trunk/Source/_javascript_Core/jit/JITOperations.cpp	2016-04-06 17:33:57 UTC (rev 199103)
+++ trunk/Source/_javascript_Core/jit/JITOperations.cpp	2016-04-06 17:36:12 UTC (rev 199104)
@@ -154,6 +154,36 @@
     return missingArgCount;
 }
 
+EncodedJSValue JIT_OPERATION operationTryGetById(ExecState* exec, StructureStubInfo* stubInfo, EncodedJSValue base, UniquedStringImpl* uid)
+{
+    VM* vm = &exec->vm();
+    NativeCallFrameTracer tracer(vm, exec);
+    Identifier ident = Identifier::fromUid(vm, uid);
+    stubInfo->tookSlowPath = true;
+
+    JSValue baseValue = JSValue::decode(base);
+    PropertySlot slot(baseValue, PropertySlot::InternalMethodType::VMInquiry);
+    baseValue.getPropertySlot(exec, ident, slot);
+
+    return JSValue::encode(slot.getPureResult());
+}
+
+EncodedJSValue JIT_OPERATION operationTryGetByIdOptimize(ExecState* exec, StructureStubInfo* stubInfo, EncodedJSValue base, UniquedStringImpl* uid)
+{
+    VM* vm = &exec->vm();
+    NativeCallFrameTracer tracer(vm, exec);
+    Identifier ident = Identifier::fromUid(vm, uid);
+
+    JSValue baseValue = JSValue::decode(base);
+    PropertySlot slot(baseValue, PropertySlot::InternalMethodType::VMInquiry);
+
+    baseValue.getPropertySlot(exec, ident, slot);
+    if (stubInfo->considerCaching() && !slot.isTaintedByProxy() && (slot.isCacheableValue() || slot.isCacheableGetter() || slot.isUnset()))
+        repatchGetByID(exec, baseValue, ident, slot, *stubInfo, GetByIDKind::Pure);
+
+    return JSValue::encode(slot.getPureResult());
+}
+
 EncodedJSValue JIT_OPERATION operationGetById(ExecState* exec, StructureStubInfo* stubInfo, EncodedJSValue base, UniquedStringImpl* uid)
 {
     VM* vm = &exec->vm();
@@ -189,7 +219,7 @@
     
     bool hasResult = baseValue.getPropertySlot(exec, ident, slot);
     if (stubInfo->considerCaching())
-        repatchGetByID(exec, baseValue, ident, slot, *stubInfo);
+        repatchGetByID(exec, baseValue, ident, slot, *stubInfo, GetByIDKind::Normal);
     
     return JSValue::encode(hasResult? slot.getValue(exec, ident) : jsUndefined());
 }

Modified: trunk/Source/_javascript_Core/jit/JITOperations.h (199103 => 199104)


--- trunk/Source/_javascript_Core/jit/JITOperations.h	2016-04-06 17:33:57 UTC (rev 199103)
+++ trunk/Source/_javascript_Core/jit/JITOperations.h	2016-04-06 17:36:12 UTC (rev 199104)
@@ -287,9 +287,10 @@
 #endif
 int32_t JIT_OPERATION operationCallArityCheck(ExecState*) WTF_INTERNAL;
 int32_t JIT_OPERATION operationConstructArityCheck(ExecState*) WTF_INTERNAL;
+EncodedJSValue JIT_OPERATION operationTryGetById(ExecState*, StructureStubInfo*, EncodedJSValue, UniquedStringImpl*) WTF_INTERNAL;
+EncodedJSValue JIT_OPERATION operationTryGetByIdOptimize(ExecState*, StructureStubInfo*, EncodedJSValue, UniquedStringImpl*) WTF_INTERNAL;
 EncodedJSValue JIT_OPERATION operationGetById(ExecState*, StructureStubInfo*, EncodedJSValue, UniquedStringImpl*) WTF_INTERNAL;
 EncodedJSValue JIT_OPERATION operationGetByIdGeneric(ExecState*, EncodedJSValue, UniquedStringImpl*) WTF_INTERNAL;
-EncodedJSValue JIT_OPERATION operationGetByIdBuildList(ExecState*, StructureStubInfo*, EncodedJSValue, UniquedStringImpl*) WTF_INTERNAL;
 EncodedJSValue JIT_OPERATION operationGetByIdOptimize(ExecState*, StructureStubInfo*, EncodedJSValue, UniquedStringImpl*) WTF_INTERNAL;
 EncodedJSValue JIT_OPERATION operationInOptimize(ExecState*, StructureStubInfo*, JSCell*, UniquedStringImpl*) WTF_INTERNAL;
 EncodedJSValue JIT_OPERATION operationIn(ExecState*, StructureStubInfo*, JSCell*, UniquedStringImpl*) WTF_INTERNAL;

Modified: trunk/Source/_javascript_Core/jit/JITPropertyAccess.cpp (199103 => 199104)


--- trunk/Source/_javascript_Core/jit/JITPropertyAccess.cpp	2016-04-06 17:33:57 UTC (rev 199103)
+++ trunk/Source/_javascript_Core/jit/JITPropertyAccess.cpp	2016-04-06 17:36:12 UTC (rev 199104)
@@ -213,7 +213,7 @@
 
     JITGetByIdGenerator gen(
         m_codeBlock, CodeOrigin(m_bytecodeOffset), CallSiteIndex(m_bytecodeOffset), RegisterSet::stubUnavailableRegisters(),
-        JSValueRegs(regT0), JSValueRegs(regT0));
+        JSValueRegs(regT0), JSValueRegs(regT0), AccessType::Get);
     gen.generateFastPath(*this);
 
     fastDoneCase = jump();
@@ -531,6 +531,43 @@
     callOperation(operationDeleteById, dst, regT0, &m_codeBlock->identifier(property));
 }
 
+void JIT::emit_op_try_get_by_id(Instruction* currentInstruction)
+{
+    int resultVReg = currentInstruction[1].u.operand;
+    int baseVReg = currentInstruction[2].u.operand;
+
+    emitGetVirtualRegister(baseVReg, regT0);
+
+    emitJumpSlowCaseIfNotJSCell(regT0, baseVReg);
+
+    JITGetByIdGenerator gen(
+        m_codeBlock, CodeOrigin(m_bytecodeOffset), CallSiteIndex(m_bytecodeOffset), RegisterSet::stubUnavailableRegisters(),
+        JSValueRegs(regT0), JSValueRegs(regT0), AccessType::GetPure);
+    gen.generateFastPath(*this);
+    addSlowCase(gen.slowPathJump());
+    m_getByIds.append(gen);
+    
+    emitPutVirtualRegister(resultVReg);
+}
+
+void JIT::emitSlow_op_try_get_by_id(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
+{
+    int resultVReg = currentInstruction[1].u.operand;
+    int baseVReg = currentInstruction[2].u.operand;
+    const Identifier* ident = &(m_codeBlock->identifier(currentInstruction[3].u.operand));
+
+    linkSlowCaseIfNotJSCell(iter, baseVReg);
+    linkSlowCase(iter);
+
+    JITGetByIdGenerator& gen = m_getByIds[m_getByIdIndex++];
+
+    Label coldPathBegin = label();
+
+    Call call = callOperation(operationTryGetByIdOptimize, resultVReg, gen.stubInfo(), regT0, ident->impl());
+    
+    gen.reportSlowPathCall(coldPathBegin, call);
+}
+
 void JIT::emit_op_get_by_id(Instruction* currentInstruction)
 {
     int resultVReg = currentInstruction[1].u.operand;
@@ -546,7 +583,7 @@
 
     JITGetByIdGenerator gen(
         m_codeBlock, CodeOrigin(m_bytecodeOffset), CallSiteIndex(m_bytecodeOffset), RegisterSet::stubUnavailableRegisters(),
-        JSValueRegs(regT0), JSValueRegs(regT0));
+        JSValueRegs(regT0), JSValueRegs(regT0), AccessType::Get);
     gen.generateFastPath(*this);
     addSlowCase(gen.slowPathJump());
     m_getByIds.append(gen);

Modified: trunk/Source/_javascript_Core/jit/JITPropertyAccess32_64.cpp (199103 => 199104)


--- trunk/Source/_javascript_Core/jit/JITPropertyAccess32_64.cpp	2016-04-06 17:33:57 UTC (rev 199103)
+++ trunk/Source/_javascript_Core/jit/JITPropertyAccess32_64.cpp	2016-04-06 17:36:12 UTC (rev 199104)
@@ -282,7 +282,7 @@
 
     JITGetByIdGenerator gen(
         m_codeBlock, CodeOrigin(m_bytecodeOffset), CallSiteIndex(currentInstruction), RegisterSet::stubUnavailableRegisters(),
-        JSValueRegs::payloadOnly(regT0), JSValueRegs(regT1, regT0));
+        JSValueRegs::payloadOnly(regT0), JSValueRegs(regT1, regT0), AccessType::Get);
     gen.generateFastPath(*this);
 
     fastDoneCase = jump();
@@ -573,6 +573,43 @@
     m_byValInstructionIndex++;
 }
 
+void JIT::emit_op_try_get_by_id(Instruction* currentInstruction)
+{
+    int dst = currentInstruction[1].u.operand;
+    int base = currentInstruction[2].u.operand;
+
+    emitLoad(base, regT1, regT0);
+    emitJumpSlowCaseIfNotJSCell(base, regT1);
+
+    JITGetByIdGenerator gen(
+        m_codeBlock, CodeOrigin(m_bytecodeOffset), CallSiteIndex(currentInstruction), RegisterSet::stubUnavailableRegisters(),
+        JSValueRegs::payloadOnly(regT0), JSValueRegs(regT1, regT0), AccessType::GetPure);
+    gen.generateFastPath(*this);
+    addSlowCase(gen.slowPathJump());
+    m_getByIds.append(gen);
+    
+    emitStore(dst, regT1, regT0);
+}
+
+void JIT::emitSlow_op_try_get_by_id(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
+{
+    int resultVReg = currentInstruction[1].u.operand;
+    int baseVReg = currentInstruction[2].u.operand;
+    const Identifier* ident = &(m_codeBlock->identifier(currentInstruction[3].u.operand));
+
+    linkSlowCaseIfNotJSCell(iter, baseVReg);
+    linkSlowCase(iter);
+
+    JITGetByIdGenerator& gen = m_getByIds[m_getByIdIndex++];
+
+    Label coldPathBegin = label();
+
+    Call call = callOperation(operationTryGetByIdOptimize, resultVReg, gen.stubInfo(), regT1, regT0, ident->impl());
+    
+    gen.reportSlowPathCall(coldPathBegin, call);
+}
+
+
 void JIT::emit_op_get_by_id(Instruction* currentInstruction)
 {
     int dst = currentInstruction[1].u.operand;
@@ -587,7 +624,7 @@
 
     JITGetByIdGenerator gen(
         m_codeBlock, CodeOrigin(m_bytecodeOffset), CallSiteIndex(currentInstruction), RegisterSet::stubUnavailableRegisters(),
-        JSValueRegs::payloadOnly(regT0), JSValueRegs(regT1, regT0));
+        JSValueRegs::payloadOnly(regT0), JSValueRegs(regT1, regT0), AccessType::Get);
     gen.generateFastPath(*this);
     addSlowCase(gen.slowPathJump());
     m_getByIds.append(gen);

Modified: trunk/Source/_javascript_Core/jit/Repatch.cpp (199103 => 199104)


--- trunk/Source/_javascript_Core/jit/Repatch.cpp	2016-04-06 17:33:57 UTC (rev 199103)
+++ trunk/Source/_javascript_Core/jit/Repatch.cpp	2016-04-06 17:36:12 UTC (rev 199104)
@@ -93,7 +93,7 @@
 
 static void repatchByIdSelfAccess(
     CodeBlock* codeBlock, StructureStubInfo& stubInfo, Structure* structure,
-    PropertyOffset offset, const FunctionPtr &slowPathFunction,
+    PropertyOffset offset, const FunctionPtr& slowPathFunction,
     bool compact)
 {
     // Only optimize once!
@@ -213,8 +213,22 @@
     return Options::forceICFailure();
 }
 
-static InlineCacheAction tryCacheGetByID(ExecState* exec, JSValue baseValue, const Identifier& propertyName, const PropertySlot& slot, StructureStubInfo& stubInfo)
+inline J_JITOperation_ESsiJI appropriateOptimizingGetByIdFunction(GetByIDKind kind)
 {
+    if (kind == GetByIDKind::Normal)
+        return operationGetByIdOptimize;
+    return operationTryGetByIdOptimize;
+}
+
+inline J_JITOperation_ESsiJI appropriateGenericGetByIdFunction(GetByIDKind kind)
+{
+    if (kind == GetByIDKind::Normal)
+        return operationGetById;
+    return operationTryGetById;
+}
+
+static InlineCacheAction tryCacheGetByID(ExecState* exec, JSValue baseValue, const Identifier& propertyName, const PropertySlot& slot, StructureStubInfo& stubInfo, GetByIDKind kind)
+{
     if (forceICFailure(exec))
         return GiveUpOnCache;
     
@@ -262,7 +276,7 @@
             && !structure->needImpurePropertyWatchpoint()
             && !loadTargetFromProxy) {
             structure->startWatchingPropertyForReplacements(vm, slot.cachedOffset());
-            repatchByIdSelfAccess(codeBlock, stubInfo, structure, slot.cachedOffset(), operationGetByIdOptimize, true);
+            repatchByIdSelfAccess(codeBlock, stubInfo, structure, slot.cachedOffset(), appropriateOptimizingGetByIdFunction(kind), true);
             stubInfo.initGetByIdSelf(codeBlock, structure, slot.cachedOffset());
             return RetryCacheLater;
         }
@@ -295,7 +309,19 @@
         if (slot.isCacheableGetter())
             getter = jsDynamicCast<JSFunction*>(slot.getterSetter()->getter());
 
-        if (!loadTargetFromProxy && getter && AccessCase::canEmitIntrinsicGetter(getter, structure))
+        if (kind == GetByIDKind::Pure) {
+            AccessCase::AccessType type;
+            if (slot.isCacheableValue())
+                type = AccessCase::Load;
+            else if (slot.isUnset())
+                type = AccessCase::Miss;
+            else if (slot.isCacheableGetter())
+                type = AccessCase::GetGetter;
+            else
+                RELEASE_ASSERT_NOT_REACHED();
+
+            newCase = AccessCase::tryGet(vm, codeBlock, type, offset, structure, conditionSet, loadTargetFromProxy, slot.watchpointSet());
+        } else if (!loadTargetFromProxy && getter && AccessCase::canEmitIntrinsicGetter(getter, structure))
             newCase = AccessCase::getIntrinsic(vm, codeBlock, getter, slot.cachedOffset(), structure, conditionSet);
         else {
             AccessCase::AccessType type;
@@ -330,12 +356,12 @@
     return RetryCacheLater;
 }
 
-void repatchGetByID(ExecState* exec, JSValue baseValue, const Identifier& propertyName, const PropertySlot& slot, StructureStubInfo& stubInfo)
+void repatchGetByID(ExecState* exec, JSValue baseValue, const Identifier& propertyName, const PropertySlot& slot, StructureStubInfo& stubInfo, GetByIDKind kind)
 {
     GCSafeConcurrentJITLocker locker(exec->codeBlock()->m_lock, exec->vm().heap);
     
-    if (tryCacheGetByID(exec, baseValue, propertyName, slot, stubInfo) == GiveUpOnCache)
-        repatchCall(exec->codeBlock(), stubInfo.callReturnLocation, operationGetById);
+    if (tryCacheGetByID(exec, baseValue, propertyName, slot, stubInfo, kind) == GiveUpOnCache)
+        repatchCall(exec->codeBlock(), stubInfo.callReturnLocation, appropriateGenericGetByIdFunction(kind));
 }
 
 static V_JITOperation_ESsiJJI appropriateGenericPutByIdFunction(const PutPropertySlot &slot, PutKind putKind)
@@ -910,9 +936,9 @@
         callLinkInfo.remove();
 }
 
-void resetGetByID(CodeBlock* codeBlock, StructureStubInfo& stubInfo)
+void resetGetByID(CodeBlock* codeBlock, StructureStubInfo& stubInfo, GetByIDKind kind)
 {
-    repatchCall(codeBlock, stubInfo.callReturnLocation, operationGetByIdOptimize);
+    repatchCall(codeBlock, stubInfo.callReturnLocation, appropriateOptimizingGetByIdFunction(kind));
     resetGetByIDCheckAndLoad(stubInfo);
     MacroAssembler::repatchJump(stubInfo.callReturnLocation.jumpAtOffset(stubInfo.patch.deltaCallToJump), stubInfo.callReturnLocation.labelAtOffset(stubInfo.patch.deltaCallToSlowCase));
 }

Modified: trunk/Source/_javascript_Core/jit/Repatch.h (199103 => 199104)


--- trunk/Source/_javascript_Core/jit/Repatch.h	2016-04-06 17:33:57 UTC (rev 199103)
+++ trunk/Source/_javascript_Core/jit/Repatch.h	2016-04-06 17:36:12 UTC (rev 199104)
@@ -35,7 +35,12 @@
 
 namespace JSC {
 
-void repatchGetByID(ExecState*, JSValue, const Identifier&, const PropertySlot&, StructureStubInfo&);
+enum class GetByIDKind {
+    Normal,
+    Pure
+};
+
+void repatchGetByID(ExecState*, JSValue, const Identifier&, const PropertySlot&, StructureStubInfo&, GetByIDKind);
 void buildGetByIDList(ExecState*, JSValue, const Identifier&, const PropertySlot&, StructureStubInfo&);
 void buildGetByIDProtoList(ExecState*, JSValue, const Identifier&, const PropertySlot&, StructureStubInfo&);
 void repatchPutByID(ExecState*, JSValue, Structure*, const Identifier&, const PutPropertySlot&, StructureStubInfo&, PutKind);
@@ -46,7 +51,7 @@
 void unlinkFor(VM&, CallLinkInfo&);
 void linkVirtualFor(ExecState*, CallLinkInfo&);
 void linkPolymorphicCall(ExecState*, CallLinkInfo&, CallVariant);
-void resetGetByID(CodeBlock*, StructureStubInfo&);
+void resetGetByID(CodeBlock*, StructureStubInfo&, GetByIDKind);
 void resetPutByID(CodeBlock*, StructureStubInfo&);
 void resetIn(CodeBlock*, StructureStubInfo&);
 

Modified: trunk/Source/_javascript_Core/jsc.cpp (199103 => 199104)


--- trunk/Source/_javascript_Core/jsc.cpp	2016-04-06 17:33:57 UTC (rev 199103)
+++ trunk/Source/_javascript_Core/jsc.cpp	2016-04-06 17:36:12 UTC (rev 199104)
@@ -23,6 +23,7 @@
 #include "config.h"
 
 #include "ArrayPrototype.h"
+#include "BuiltinExecutables.h"
 #include "ButterflyInlines.h"
 #include "BytecodeGenerator.h"
 #include "CodeBlock.h"
@@ -32,6 +33,7 @@
 #include "Disassembler.h"
 #include "Exception.h"
 #include "ExceptionHelpers.h"
+#include "GetterSetter.h"
 #include "HeapProfiler.h"
 #include "HeapSnapshotBuilder.h"
 #include "HeapStatistics.h"
@@ -552,6 +554,7 @@
 static EncodedJSValue JSC_HOST_CALL functionCreateRuntimeArray(ExecState*);
 static EncodedJSValue JSC_HOST_CALL functionCreateImpureGetter(ExecState*);
 static EncodedJSValue JSC_HOST_CALL functionCreateCustomGetterObject(ExecState*);
+static EncodedJSValue JSC_HOST_CALL functionCreateBuiltin(ExecState*);
 static EncodedJSValue JSC_HOST_CALL functionSetImpureGetterDelegate(ExecState*);
 
 static EncodedJSValue JSC_HOST_CALL functionSetElementRoot(ExecState*);
@@ -572,6 +575,7 @@
 static EncodedJSValue JSC_HOST_CALL functionForceGCSlowPaths(ExecState*);
 static EncodedJSValue JSC_HOST_CALL functionHeapSize(ExecState*);
 static EncodedJSValue JSC_HOST_CALL functionAddressOf(ExecState*);
+static EncodedJSValue JSC_HOST_CALL functionGetGetterSetter(ExecState*);
 #ifndef NDEBUG
 static EncodedJSValue JSC_HOST_CALL functionDumpCallFrame(ExecState*);
 #endif
@@ -743,6 +747,7 @@
         addFunction(vm, "forceGCSlowPaths", functionForceGCSlowPaths, 0);
         addFunction(vm, "gcHeapSize", functionHeapSize, 0);
         addFunction(vm, "addressOf", functionAddressOf, 1);
+        addFunction(vm, "getGetterSetter", functionGetGetterSetter, 2);
 #ifndef NDEBUG
         addFunction(vm, "dumpCallFrame", functionDumpCallFrame, 0);
 #endif
@@ -792,6 +797,7 @@
 
         addFunction(vm, "createImpureGetter", functionCreateImpureGetter, 1);
         addFunction(vm, "createCustomGetterObject", functionCreateCustomGetterObject, 0);
+        addFunction(vm, "createBuiltin", functionCreateBuiltin, 2);
         addFunction(vm, "setImpureGetterDelegate", functionSetImpureGetterDelegate, 2);
 
         addFunction(vm, "dumpTypesForAllVariables", functionDumpTypesForAllVariables , 0);
@@ -1332,6 +1338,30 @@
     return returnValue;
 }
 
+static EncodedJSValue JSC_HOST_CALL functionGetGetterSetter(ExecState* exec)
+{
+    JSValue value = exec->argument(0);
+    if (!value.isObject())
+        return JSValue::encode(jsUndefined());
+
+    JSValue property = exec->argument(1);
+    if (!property.isString())
+        return JSValue::encode(jsUndefined());
+
+    Identifier ident = Identifier::fromString(&exec->vm(), property.toString(exec)->value(exec));
+
+    PropertySlot slot(value, PropertySlot::InternalMethodType::VMInquiry);
+    value.getPropertySlot(exec, ident, slot);
+
+    JSValue result;
+    if (slot.isCacheableGetter())
+        result = slot.getterSetter();
+    else
+        result = jsNull();
+
+    return JSValue::encode(result);
+}
+
 EncodedJSValue JSC_HOST_CALL functionVersion(ExecState*)
 {
     // We need this function for compatibility with the Mozilla JS tests but for now
@@ -1721,6 +1751,22 @@
     return JSValue::encode(jsUndefined());
 }
 
+EncodedJSValue JSC_HOST_CALL functionCreateBuiltin(ExecState* exec)
+{
+    if (exec->argumentCount() < 1 || !exec->argument(0).isString())
+        return JSValue::encode(jsUndefined());
+
+    String functionText = exec->argument(0).toString(exec)->value(exec);
+    if (exec->hadException())
+        return JSValue::encode(JSValue());
+
+    VM& vm = exec->vm();
+    const SourceCode& source = makeSource(functionText);
+    JSFunction* func = JSFunction::createBuiltinFunction(vm, BuiltinExecutables::createExecutable(vm, source, Identifier::fromString(&vm, "foo"), ConstructorKind::None, ConstructAbility::CannotConstruct)->link(vm, source), exec->lexicalGlobalObject());
+
+    return JSValue::encode(func);
+}
+
 EncodedJSValue JSC_HOST_CALL functionCheckModuleSyntax(ExecState* exec)
 {
     String source = exec->argument(0).toString(exec)->value(exec);

Modified: trunk/Source/_javascript_Core/llint/LLIntData.cpp (199103 => 199104)


--- trunk/Source/_javascript_Core/llint/LLIntData.cpp	2016-04-06 17:33:57 UTC (rev 199103)
+++ trunk/Source/_javascript_Core/llint/LLIntData.cpp	2016-04-06 17:36:12 UTC (rev 199104)
@@ -144,9 +144,9 @@
     
     STATIC_ASSERT(StringType == 6);
     STATIC_ASSERT(SymbolType == 7);
-    STATIC_ASSERT(ObjectType == 21);
-    STATIC_ASSERT(FinalObjectType == 22);
-    STATIC_ASSERT(JSFunctionType == 24);
+    STATIC_ASSERT(ObjectType == 20);
+    STATIC_ASSERT(FinalObjectType == 21);
+    STATIC_ASSERT(JSFunctionType == 23);
     STATIC_ASSERT(MasqueradesAsUndefined == 1);
     STATIC_ASSERT(ImplementsDefaultHasInstance == 2);
     STATIC_ASSERT(FirstConstantRegisterIndex == 0x40000000);

Modified: trunk/Source/_javascript_Core/llint/LLIntSlowPaths.cpp (199103 => 199104)


--- trunk/Source/_javascript_Core/llint/LLIntSlowPaths.cpp	2016-04-06 17:33:57 UTC (rev 199103)
+++ trunk/Source/_javascript_Core/llint/LLIntSlowPaths.cpp	2016-04-06 17:36:12 UTC (rev 199104)
@@ -545,6 +545,19 @@
     LLINT_RETURN(result);
 }
 
+LLINT_SLOW_PATH_DECL(slow_path_try_get_by_id)
+{
+    LLINT_BEGIN();
+    CodeBlock* codeBlock = exec->codeBlock();
+    const Identifier& ident = codeBlock->identifier(pc[3].u.operand);
+    JSValue baseValue = LLINT_OP_C(2).jsValue();
+    PropertySlot slot(baseValue, PropertySlot::PropertySlot::InternalMethodType::VMInquiry);
+
+    baseValue.getPropertySlot(exec, ident, slot);
+
+    LLINT_RETURN(slot.getPureResult());
+}
+
 LLINT_SLOW_PATH_DECL(slow_path_get_by_id)
 {
     LLINT_BEGIN();

Modified: trunk/Source/_javascript_Core/llint/LLIntSlowPaths.h (199103 => 199104)


--- trunk/Source/_javascript_Core/llint/LLIntSlowPaths.h	2016-04-06 17:33:57 UTC (rev 199103)
+++ trunk/Source/_javascript_Core/llint/LLIntSlowPaths.h	2016-04-06 17:36:12 UTC (rev 199104)
@@ -69,6 +69,7 @@
 LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_new_regexp);
 LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_instanceof);
 LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_instanceof_custom);
+LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_try_get_by_id);
 LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_get_by_id);
 LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_get_arguments_length);
 LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_put_by_id);

Modified: trunk/Source/_javascript_Core/llint/LowLevelInterpreter.asm (199103 => 199104)


--- trunk/Source/_javascript_Core/llint/LowLevelInterpreter.asm	2016-04-06 17:33:57 UTC (rev 199103)
+++ trunk/Source/_javascript_Core/llint/LowLevelInterpreter.asm	2016-04-06 17:36:12 UTC (rev 199104)
@@ -326,9 +326,9 @@
 # Type constants.
 const StringType = 6
 const SymbolType = 7
-const ObjectType = 21
-const FinalObjectType = 22
-const JSFunctionType = 24
+const ObjectType = 20
+const FinalObjectType = 21
+const JSFunctionType = 23
 
 # Type flags constants.
 const MasqueradesAsUndefined = 1
@@ -1301,6 +1301,12 @@
     dispatch(4)
 
 
+_llint_op_try_get_by_id:
+    traceExecution()
+    callSlowPath(_llint_slow_path_try_get_by_id)
+    dispatch(4)
+
+
 _llint_op_del_by_id:
     traceExecution()
     callSlowPath(_llint_slow_path_del_by_id)

Modified: trunk/Source/_javascript_Core/runtime/GetterSetter.cpp (199103 => 199104)


--- trunk/Source/_javascript_Core/runtime/GetterSetter.cpp	2016-04-06 17:33:57 UTC (rev 199103)
+++ trunk/Source/_javascript_Core/runtime/GetterSetter.cpp	2016-04-06 17:36:12 UTC (rev 199104)
@@ -33,7 +33,7 @@
 
 STATIC_ASSERT_IS_TRIVIALLY_DESTRUCTIBLE(GetterSetter);
 
-const ClassInfo GetterSetter::s_info = { "GetterSetter", 0, 0, CREATE_METHOD_TABLE(GetterSetter) };
+const ClassInfo GetterSetter::s_info = { "GetterSetter", &Base::s_info, 0, CREATE_METHOD_TABLE(GetterSetter) };
 
 void GetterSetter::visitChildren(JSCell* cell, SlotVisitor& visitor)
 {

Modified: trunk/Source/_javascript_Core/runtime/GetterSetter.h (199103 => 199104)


--- trunk/Source/_javascript_Core/runtime/GetterSetter.h	2016-04-06 17:33:57 UTC (rev 199103)
+++ trunk/Source/_javascript_Core/runtime/GetterSetter.h	2016-04-06 17:36:12 UTC (rev 199104)
@@ -41,21 +41,21 @@
 // that if a property holding a GetterSetter reference is constant-inferred and
 // that constant is observed to have a non-null setter (or getter) then we can
 // constant fold that setter (or getter).
-class GetterSetter final : public JSCell {
+class GetterSetter final : public JSNonFinalObject {
     friend class JIT;
-
+    typedef JSNonFinalObject Base;
 private:
     GetterSetter(VM& vm, JSGlobalObject* globalObject)
-        : JSCell(vm, vm.getterSetterStructure.get())
+        : Base(vm, vm.getterSetterStructure.get())
     {
         m_getter.set(vm, this, globalObject->nullGetterFunction());
         m_setter.set(vm, this, globalObject->nullSetterFunction());
     }
 
 public:
-    typedef JSCell Base;
-    static const unsigned StructureFlags = Base::StructureFlags | StructureIsImmortal;
 
+    static const unsigned StructureFlags = Base::StructureFlags | OverridesGetOwnPropertySlot | StructureIsImmortal;
+
     static GetterSetter* create(VM& vm, JSGlobalObject* globalObject)
     {
         GetterSetter* getterSetter = new (NotNull, allocateCell<GetterSetter>(vm.heap)) GetterSetter(vm, globalObject);
@@ -128,8 +128,13 @@
         return OBJECT_OFFSETOF(GetterSetter, m_setter);
     }
 
-    DECLARE_INFO;
+    DECLARE_EXPORT_INFO;
 
+    static bool getOwnPropertySlot(JSObject*, ExecState*, PropertyName, PropertySlot&) { RELEASE_ASSERT_NOT_REACHED(); return false; }
+    static bool put(JSCell*, ExecState*, PropertyName, JSValue, PutPropertySlot&) { RELEASE_ASSERT_NOT_REACHED(); return false; }
+    static bool defineOwnProperty(JSObject*, ExecState*, PropertyName, const PropertyDescriptor&, bool) { RELEASE_ASSERT_NOT_REACHED(); return false; }
+    static bool deleteProperty(JSCell*, ExecState*, PropertyName) { RELEASE_ASSERT_NOT_REACHED(); return false; }
+
 private:
     WriteBarrier<JSObject> m_getter;
     WriteBarrier<JSObject> m_setter;  

Modified: trunk/Source/_javascript_Core/runtime/JSType.h (199103 => 199104)


--- trunk/Source/_javascript_Core/runtime/JSType.h	2016-04-06 17:33:57 UTC (rev 199103)
+++ trunk/Source/_javascript_Core/runtime/JSType.h	2016-04-06 17:36:12 UTC (rev 199104)
@@ -35,7 +35,6 @@
     StringType,
     SymbolType,
 
-    GetterSetterType,
     CustomGetterSetterType,
     APIValueWrapperType,
 
@@ -75,6 +74,7 @@
     Float64ArrayType,
     DataViewType,
 
+    GetterSetterType,
     GlobalObjectType,
     LexicalEnvironmentType,
     GlobalLexicalEnvironmentType,

Modified: trunk/Source/_javascript_Core/runtime/PropertySlot.cpp (199103 => 199104)


--- trunk/Source/_javascript_Core/runtime/PropertySlot.cpp	2016-04-06 17:33:57 UTC (rev 199103)
+++ trunk/Source/_javascript_Core/runtime/PropertySlot.cpp	2016-04-06 17:36:12 UTC (rev 199104)
@@ -39,4 +39,21 @@
     return JSValue::decode(m_data.custom.getValue(exec, JSValue::encode(thisValue), propertyName));
 }
 
+JSValue PropertySlot::getPureResult() const
+{
+    JSValue result;
+    if (isTaintedByProxy())
+        result = jsNull();
+    else if (isCacheableValue())
+        result = JSValue::decode(m_data.value);
+    else if (isCacheableGetter())
+        result = getterSetter();
+    else if (isUnset())
+        result = jsUndefined();
+    else
+        result = jsNull();
+    
+    return result;
+}
+
 } // namespace JSC

Modified: trunk/Source/_javascript_Core/runtime/PropertySlot.h (199103 => 199104)


--- trunk/Source/_javascript_Core/runtime/PropertySlot.h	2016-04-06 17:33:57 UTC (rev 199103)
+++ trunk/Source/_javascript_Core/runtime/PropertySlot.h	2016-04-06 17:36:12 UTC (rev 199104)
@@ -94,6 +94,7 @@
 
     JSValue getValue(ExecState*, PropertyName) const;
     JSValue getValue(ExecState*, unsigned propertyName) const;
+    JSValue getPureResult() const;
 
     bool isCacheable() const { return m_cacheability == CachingAllowed && m_offset != invalidOffset; }
     bool isUnset() const { return m_propertyType == TypeUnset; }

Modified: trunk/Source/_javascript_Core/runtime/ProxyObject.cpp (199103 => 199104)


--- trunk/Source/_javascript_Core/runtime/ProxyObject.cpp	2016-04-06 17:33:57 UTC (rev 199103)
+++ trunk/Source/_javascript_Core/runtime/ProxyObject.cpp	2016-04-06 17:36:12 UTC (rev 199104)
@@ -332,8 +332,7 @@
 bool ProxyObject::getOwnPropertySlotCommon(ExecState* exec, PropertyName propertyName, PropertySlot& slot)
 {
     slot.disableCaching();
-    if (slot.internalMethodType() != PropertySlot::InternalMethodType::VMInquiry)
-        slot.setIsTaintedByProxy();
+    slot.setIsTaintedByProxy();
     switch (slot.internalMethodType()) {
     case PropertySlot::InternalMethodType::Get:
         slot.setCustom(this, CustomAccessor, performProxyGet);

Added: trunk/Source/_javascript_Core/tests/stress/try-get-by-id.js (0 => 199104)


--- trunk/Source/_javascript_Core/tests/stress/try-get-by-id.js	                        (rev 0)
+++ trunk/Source/_javascript_Core/tests/stress/try-get-by-id.js	2016-04-06 17:36:12 UTC (rev 199104)
@@ -0,0 +1,117 @@
+function tryGetByIdText(propertyName) { return `(function (base) { return @tryGetById(base, '${propertyName}'); })`; }
+
+
+// Test get value off object.
+{
+    let getCaller = createBuiltin(tryGetByIdText("caller"));
+    noInline(getCaller);
+    let obj = {caller: 1};
+
+    for (let i = 0; i < 100000; i++) {
+        if (getCaller(obj) !== 1)
+            throw new Error("wrong on iteration: " + i);
+    }
+}
+
+// Test slot is custom function trap for a value.
+{
+    let getCaller = createBuiltin(tryGetByIdText("caller"));
+    noInline(getCaller);
+    let func = function () {};
+
+    for (let i = 0; i < 100000; i++) {
+        if (getCaller(func) !== null)
+            throw new Error("wrong on iteration: " + i);
+    }
+}
+
+// Test slot is a GetterSetter.
+{
+    let get = createBuiltin(tryGetByIdText("getterSetter"));
+    noInline(get);
+    let obj = {};
+    Object.defineProperty(obj, "getterSetter", { get: function () { throw new Error("should not be called"); } });
+
+    for (let i = 0; i < 100000; i++) {
+        if (get(obj) !== getGetterSetter(obj, "getterSetter"))
+            throw new Error("wrong on iteration: " + i);
+    }
+}
+
+// Test slot is unset.
+{
+    let get = createBuiltin(tryGetByIdText("getterSetter"));
+    noInline(get);
+    let obj = {};
+
+    for (let i = 0; i < 100000; i++) {
+        if (get(obj) !== undefined)
+            throw new Error("wrong on iteration: " + i);
+    }
+}
+
+// Test slot is on a proxy with value.
+{
+    let get = createBuiltin(tryGetByIdText("value"));
+    noInline(get);
+
+    let obj = {value: 1};
+    let p = new Proxy(obj, { get: function() { throw new Error("should not be called"); } });
+
+    for (let i = 0; i < 100000; i++) {
+        if (get(p) !== null)
+            throw new Error("wrong on iteration: " + i);
+    }
+}
+
+// Test mutating inline cache.
+{
+    let get = createBuiltin(tryGetByIdText("caller"));
+    noInline(get);
+
+    let obj = {caller : 1};
+    let func = function() {};
+
+    for (let i = 0; i < 100000; i++) {
+        if (i % 100 === 0) {
+            if (get(func) !== null)
+                throw new Error("wrong on iteration: " + i);
+        } else {
+            if (get(obj) !== 1)
+                throw new Error("wrong on iteration: " + i);
+        }
+    }
+}
+
+// Test new type on each iteration.
+{
+    let get = createBuiltin(tryGetByIdText("caller"));
+    noInline(get);
+
+    let func = function() {};
+
+    for (let i = 0; i < 100000; i++) {
+        if (i % 100 === 0) {
+            if (get(func) !== null)
+                throw new Error("wrong on iteration: " + i);
+        } else {
+            let obj = {caller : 1};
+            if (get(obj) !== 1)
+                throw new Error("wrong on iteration: " + i);
+        }
+    }
+}
+
+// Test with array length. This is null because the value is not cacheable.
+{
+    let get = createBuiltin(tryGetByIdText("length"));
+    noInline(get);
+
+    let arr = [];
+
+    for (let i = 0; i < 100000; i++) {
+        if (get(arr) !== null)
+            throw new Error("wrong on iteration: " + i);
+
+    }
+}
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to