Title: [201363] trunk/Source
Revision
201363
Author
[email protected]
Date
2016-05-24 16:49:57 -0700 (Tue, 24 May 2016)

Log Message

LLInt should be able to cache prototype loads for values in GetById
https://bugs.webkit.org/show_bug.cgi?id=158032

Reviewed by Filip Pizlo.

Source/_javascript_Core:

This patch adds prototype value caching to the LLInt for op_get_by_id.
Two previously unused words in the op_get_by_id bytecode have been
repurposed to hold extra information for the cache. The first is a
counter that records the number of get_by_ids that hit a cacheable value
on a prototype. When the counter is decremented from one to zero we
attempt to cache the prototype load, which will be discussed further
below. The second word is used to hold the prototype object when we have
started caching.

When the counter is decremented to zero we first attempt to generate and
watch the property conditions needed to ensure the validity of prototype
load. If the watchpoints are successfully created and installed we
replace the op_get_by_id opcode with the new op_get_by_id_proto_load
opcode, which tells the LLInt to use the cache prototype object for the
load rather than the base value.

Prior to this patch there was not LLInt specific data onCodeBlocks.
Since the CodeBlock needs to own the Watchpoints for the cache, a weak
map from each base structure to a bag of Watchpoints created for that
structure by some op_get_by_id has been added to the CodeBlock. During
GC, if we find that the a structure in the map has not been marked we
free the associated bag on the CodeBlock.

* _javascript_Core.xcodeproj/project.pbxproj:
* bytecode/BytecodeList.json:
* bytecode/BytecodeUseDef.h:
(JSC::computeUsesForBytecodeOffset):
(JSC::computeDefsForBytecodeOffset):
* bytecode/CodeBlock.cpp:
(JSC::CodeBlock::printGetByIdOp):
(JSC::CodeBlock::printGetByIdCacheStatus):
(JSC::CodeBlock::dumpBytecode):
(JSC::CodeBlock::finalizeLLIntInlineCaches):
* bytecode/CodeBlock.h:
(JSC::CodeBlock::llintGetByIdWatchpointMap):
(JSC::clearLLIntGetByIdCache):
* bytecode/GetByIdStatus.cpp:
(JSC::GetByIdStatus::computeFromLLInt):
* bytecode/LLIntPrototypeLoadAdaptiveStructureWatchpoint.cpp: Added.
(JSC::LLIntPrototypeLoadAdaptiveStructureWatchpoint::LLIntPrototypeLoadAdaptiveStructureWatchpoint):
(JSC::LLIntPrototypeLoadAdaptiveStructureWatchpoint::install):
(JSC::LLIntPrototypeLoadAdaptiveStructureWatchpoint::fireInternal):
* bytecode/LLIntPrototypeLoadAdaptiveStructureWatchpoint.h: Added.
* bytecode/ObjectPropertyConditionSet.cpp:
(JSC::ObjectPropertyConditionSet::isValidAndWatchable):
* bytecode/ObjectPropertyConditionSet.h:
* bytecompiler/BytecodeGenerator.cpp:
(JSC::BytecodeGenerator::emitGetById):
* dfg/DFGByteCodeParser.cpp:
(JSC::DFG::ByteCodeParser::parseBlock):
* dfg/DFGCapabilities.cpp:
(JSC::DFG::capabilityLevel):
* jit/JIT.cpp:
(JSC::JIT::privateCompileMainPass):
(JSC::JIT::privateCompileSlowCases):
* llint/LLIntSlowPaths.cpp:
(JSC::LLInt::setupGetByIdPrototypeCache):
(JSC::LLInt::LLINT_SLOW_PATH_DECL):
* llint/LLIntSlowPaths.h:
* llint/LowLevelInterpreter32_64.asm:
* llint/LowLevelInterpreter64.asm:
* runtime/Options.h:
* tests/stress/llint-get-by-id-cache-prototype-load-from-dictionary.js: Added.
(test):

Source/WTF:

Add move constructors/initializers to Bags.

* wtf/Bag.h:
(WTF::Bag::Bag):
(WTF::Bag::operator=):

Modified Paths

Added Paths

Diff

Modified: trunk/Source/_javascript_Core/CMakeLists.txt (201362 => 201363)


--- trunk/Source/_javascript_Core/CMakeLists.txt	2016-05-24 23:09:54 UTC (rev 201362)
+++ trunk/Source/_javascript_Core/CMakeLists.txt	2016-05-24 23:49:57 UTC (rev 201363)
@@ -202,6 +202,7 @@
     bytecode/InlineCallFrame.cpp
     bytecode/InlineCallFrameSet.cpp
     bytecode/JumpTable.cpp
+    bytecode/LLIntPrototypeLoadAdaptiveStructureWatchpoint.cpp
     bytecode/LazyOperandValueProfile.cpp
     bytecode/MethodOfGettingAValueProfile.cpp
     bytecode/ObjectPropertyCondition.cpp

Modified: trunk/Source/_javascript_Core/ChangeLog (201362 => 201363)


--- trunk/Source/_javascript_Core/ChangeLog	2016-05-24 23:09:54 UTC (rev 201362)
+++ trunk/Source/_javascript_Core/ChangeLog	2016-05-24 23:49:57 UTC (rev 201363)
@@ -1,5 +1,77 @@
 2016-05-24  Keith Miller  <[email protected]>
 
+        LLInt should be able to cache prototype loads for values in GetById
+        https://bugs.webkit.org/show_bug.cgi?id=158032
+
+        Reviewed by Filip Pizlo.
+
+        This patch adds prototype value caching to the LLInt for op_get_by_id.
+        Two previously unused words in the op_get_by_id bytecode have been
+        repurposed to hold extra information for the cache. The first is a
+        counter that records the number of get_by_ids that hit a cacheable value
+        on a prototype. When the counter is decremented from one to zero we
+        attempt to cache the prototype load, which will be discussed further
+        below. The second word is used to hold the prototype object when we have
+        started caching.
+
+        When the counter is decremented to zero we first attempt to generate and
+        watch the property conditions needed to ensure the validity of prototype
+        load. If the watchpoints are successfully created and installed we
+        replace the op_get_by_id opcode with the new op_get_by_id_proto_load
+        opcode, which tells the LLInt to use the cache prototype object for the
+        load rather than the base value.
+
+        Prior to this patch there was not LLInt specific data onCodeBlocks.
+        Since the CodeBlock needs to own the Watchpoints for the cache, a weak
+        map from each base structure to a bag of Watchpoints created for that
+        structure by some op_get_by_id has been added to the CodeBlock. During
+        GC, if we find that the a structure in the map has not been marked we
+        free the associated bag on the CodeBlock.
+
+        * _javascript_Core.xcodeproj/project.pbxproj:
+        * bytecode/BytecodeList.json:
+        * bytecode/BytecodeUseDef.h:
+        (JSC::computeUsesForBytecodeOffset):
+        (JSC::computeDefsForBytecodeOffset):
+        * bytecode/CodeBlock.cpp:
+        (JSC::CodeBlock::printGetByIdOp):
+        (JSC::CodeBlock::printGetByIdCacheStatus):
+        (JSC::CodeBlock::dumpBytecode):
+        (JSC::CodeBlock::finalizeLLIntInlineCaches):
+        * bytecode/CodeBlock.h:
+        (JSC::CodeBlock::llintGetByIdWatchpointMap):
+        (JSC::clearLLIntGetByIdCache):
+        * bytecode/GetByIdStatus.cpp:
+        (JSC::GetByIdStatus::computeFromLLInt):
+        * bytecode/LLIntPrototypeLoadAdaptiveStructureWatchpoint.cpp: Added.
+        (JSC::LLIntPrototypeLoadAdaptiveStructureWatchpoint::LLIntPrototypeLoadAdaptiveStructureWatchpoint):
+        (JSC::LLIntPrototypeLoadAdaptiveStructureWatchpoint::install):
+        (JSC::LLIntPrototypeLoadAdaptiveStructureWatchpoint::fireInternal):
+        * bytecode/LLIntPrototypeLoadAdaptiveStructureWatchpoint.h: Added.
+        * bytecode/ObjectPropertyConditionSet.cpp:
+        (JSC::ObjectPropertyConditionSet::isValidAndWatchable):
+        * bytecode/ObjectPropertyConditionSet.h:
+        * bytecompiler/BytecodeGenerator.cpp:
+        (JSC::BytecodeGenerator::emitGetById):
+        * dfg/DFGByteCodeParser.cpp:
+        (JSC::DFG::ByteCodeParser::parseBlock):
+        * dfg/DFGCapabilities.cpp:
+        (JSC::DFG::capabilityLevel):
+        * jit/JIT.cpp:
+        (JSC::JIT::privateCompileMainPass):
+        (JSC::JIT::privateCompileSlowCases):
+        * llint/LLIntSlowPaths.cpp:
+        (JSC::LLInt::setupGetByIdPrototypeCache):
+        (JSC::LLInt::LLINT_SLOW_PATH_DECL):
+        * llint/LLIntSlowPaths.h:
+        * llint/LowLevelInterpreter32_64.asm:
+        * llint/LowLevelInterpreter64.asm:
+        * runtime/Options.h:
+        * tests/stress/llint-get-by-id-cache-prototype-load-from-dictionary.js: Added.
+        (test):
+
+2016-05-24  Keith Miller  <[email protected]>
+
         We should be able to use the sampling profiler with DRT/WTR.
         https://bugs.webkit.org/show_bug.cgi?id=158041
 

Modified: trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj (201362 => 201363)


--- trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj	2016-05-24 23:09:54 UTC (rev 201362)
+++ trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj	2016-05-24 23:49:57 UTC (rev 201363)
@@ -1181,6 +1181,8 @@
 		5370B4F61BF26205005C40FC /* AdaptiveInferredPropertyValueWatchpointBase.h in Headers */ = {isa = PBXBuildFile; fileRef = 5370B4F41BF25EA2005C40FC /* AdaptiveInferredPropertyValueWatchpointBase.h */; };
 		53917E7B1B7906FA000EBD33 /* JSGenericTypedArrayViewPrototypeFunctions.h in Headers */ = {isa = PBXBuildFile; fileRef = 53917E7A1B7906E4000EBD33 /* JSGenericTypedArrayViewPrototypeFunctions.h */; };
 		53F6BF6D1C3F060A00F41E5D /* InternalFunctionAllocationProfile.h in Headers */ = {isa = PBXBuildFile; fileRef = 53F6BF6C1C3F060A00F41E5D /* InternalFunctionAllocationProfile.h */; settings = {ATTRIBUTES = (Private, ); }; };
+		53FA2AE11CF37F3F0022711D /* LLIntPrototypeLoadAdaptiveStructureWatchpoint.h in Headers */ = {isa = PBXBuildFile; fileRef = 53FA2AE01CF37F3F0022711D /* LLIntPrototypeLoadAdaptiveStructureWatchpoint.h */; settings = {ATTRIBUTES = (Private, ); }; };
+		53FA2AE31CF380390022711D /* LLIntPrototypeLoadAdaptiveStructureWatchpoint.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 53FA2AE21CF380390022711D /* LLIntPrototypeLoadAdaptiveStructureWatchpoint.cpp */; };
 		5D5D8AD10E0D0EBE00F9C692 /* libedit.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 5D5D8AD00E0D0EBE00F9C692 /* libedit.dylib */; };
 		5DBB151B131D0B310056AD36 /* testapi.js in Copy Support Script */ = {isa = PBXBuildFile; fileRef = 14D857740A4696C80032146C /* testapi.js */; };
 		5DBB1525131D0BD70056AD36 /* minidom.js in Copy Support Script */ = {isa = PBXBuildFile; fileRef = 1412110D0A48788700480255 /* minidom.js */; };
@@ -3321,6 +3323,8 @@
 		53917E831B791CB8000EBD33 /* TypedArrayPrototype.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode._javascript_; name = TypedArrayPrototype.js; path = builtins/TypedArrayPrototype.js; sourceTree = SOURCE_ROOT; };
 		53F256E11B87E28000B4B768 /* JSTypedArrayViewPrototype.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSTypedArrayViewPrototype.cpp; sourceTree = "<group>"; };
 		53F6BF6C1C3F060A00F41E5D /* InternalFunctionAllocationProfile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InternalFunctionAllocationProfile.h; sourceTree = "<group>"; };
+		53FA2AE01CF37F3F0022711D /* LLIntPrototypeLoadAdaptiveStructureWatchpoint.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LLIntPrototypeLoadAdaptiveStructureWatchpoint.h; sourceTree = "<group>"; };
+		53FA2AE21CF380390022711D /* LLIntPrototypeLoadAdaptiveStructureWatchpoint.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = LLIntPrototypeLoadAdaptiveStructureWatchpoint.cpp; sourceTree = "<group>"; };
 		593D43CCA0BBE06D89C59707 /* MapDataInlines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MapDataInlines.h; sourceTree = "<group>"; };
 		5D5D8AD00E0D0EBE00F9C692 /* libedit.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libedit.dylib; path = /usr/lib/libedit.dylib; sourceTree = "<absolute>"; };
 		5DAFD6CB146B686300FBEFB4 /* JSC.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = JSC.xcconfig; sourceTree = "<group>"; };
@@ -6575,6 +6579,8 @@
 				0FB5467814F5C468002C2989 /* LazyOperandValueProfile.cpp */,
 				0FB5467614F59AD1002C2989 /* LazyOperandValueProfile.h */,
 				0F0FC45814BD15F100B81154 /* LLIntCallLinkInfo.h */,
+				53FA2AE21CF380390022711D /* LLIntPrototypeLoadAdaptiveStructureWatchpoint.cpp */,
+				53FA2AE01CF37F3F0022711D /* LLIntPrototypeLoadAdaptiveStructureWatchpoint.h */,
 				0FB5467C14F5CFD3002C2989 /* MethodOfGettingAValueProfile.cpp */,
 				0FB5467A14F5C7D4002C2989 /* MethodOfGettingAValueProfile.h */,
 				14CA958C16AB50FA00938A06 /* ObjectAllocationProfile.h */,
@@ -7910,6 +7916,7 @@
 				0FF7168C15A3B235008F5DAA /* PropertyOffset.h in Headers */,
 				BC18C4550E16F5CD00B34460 /* PropertySlot.h in Headers */,
 				0FB7F39C15ED8E4600F167B2 /* PropertyStorage.h in Headers */,
+				53FA2AE11CF37F3F0022711D /* LLIntPrototypeLoadAdaptiveStructureWatchpoint.h in Headers */,
 				BC18C4560E16F5CD00B34460 /* Protect.h in Headers */,
 				1474C33B16AA2D950062F01D /* PrototypeMap.h in Headers */,
 				0F5780A218FE1E98001E72D9 /* PureNaN.h in Headers */,
@@ -8635,6 +8642,7 @@
 				65C02850171795E200351E35 /* ARMv7Disassembler.cpp in Sources */,
 				65C0285C1717966800351E35 /* ARMv7DOpcode.cpp in Sources */,
 				0F8335B71639C1E6001443B5 /* ArrayAllocationProfile.cpp in Sources */,
+				53FA2AE31CF380390022711D /* LLIntPrototypeLoadAdaptiveStructureWatchpoint.cpp in Sources */,
 				A7A8AF3417ADB5F3005AB174 /* ArrayBuffer.cpp in Sources */,
 				0FFC99D4184EE318009C10AB /* ArrayBufferNeuteringWatchpoint.cpp in Sources */,
 				A7A8AF3617ADB5F3005AB174 /* ArrayBufferView.cpp in Sources */,

Modified: trunk/Source/_javascript_Core/bytecode/BytecodeList.json (201362 => 201363)


--- trunk/Source/_javascript_Core/bytecode/BytecodeList.json	2016-05-24 23:09:54 UTC (rev 201362)
+++ trunk/Source/_javascript_Core/bytecode/BytecodeList.json	2016-05-24 23:49:57 UTC (rev 201363)
@@ -58,11 +58,12 @@
             { "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_array_length", "length" : 9 },
             { "name" : "op_get_by_id", "length" : 9  },
+            { "name" : "op_get_by_id_proto_load", "length" : 9 },
             { "name" : "op_get_by_id_with_this", "length" : 5 },
             { "name" : "op_get_by_val_with_this", "length" : 5 },
-            { "name" : "op_get_array_length", "length" : 9 },
+            { "name" : "op_try_get_by_id", "length" : 4 },
             { "name" : "op_put_by_id", "length" : 9 },
             { "name" : "op_put_by_id_with_this", "length" : 5 },
             { "name" : "op_del_by_id", "length" : 4 },

Modified: trunk/Source/_javascript_Core/bytecode/BytecodeUseDef.h (201362 => 201363)


--- trunk/Source/_javascript_Core/bytecode/BytecodeUseDef.h	2016-05-24 23:09:54 UTC (rev 201362)
+++ trunk/Source/_javascript_Core/bytecode/BytecodeUseDef.h	2016-05-24 23:49:57 UTC (rev 201363)
@@ -158,6 +158,7 @@
     case op_to_primitive:
     case op_try_get_by_id:
     case op_get_by_id:
+    case op_get_by_id_proto_load:
     case op_get_array_length:
     case op_typeof:
     case op_is_empty:
@@ -392,6 +393,7 @@
     case op_construct:
     case op_try_get_by_id:
     case op_get_by_id:
+    case op_get_by_id_proto_load:
     case op_get_by_id_with_this:
     case op_get_by_val_with_this:
     case op_get_array_length:

Modified: trunk/Source/_javascript_Core/bytecode/CodeBlock.cpp (201362 => 201363)


--- trunk/Source/_javascript_Core/bytecode/CodeBlock.cpp	2016-05-24 23:09:54 UTC (rev 201362)
+++ trunk/Source/_javascript_Core/bytecode/CodeBlock.cpp	2016-05-24 23:49:57 UTC (rev 201363)
@@ -50,6 +50,7 @@
 #include "JSLexicalEnvironment.h"
 #include "JSModuleEnvironment.h"
 #include "LLIntEntrypoint.h"
+#include "LLIntPrototypeLoadAdaptiveStructureWatchpoint.h"
 #include "LowLevelInterpreter.h"
 #include "JSCInlines.h"
 #include "PCToCodeOriginMap.h"
@@ -345,6 +346,9 @@
     case op_get_by_id:
         op = "get_by_id";
         break;
+    case op_get_by_id_proto_load:
+        op = "get_by_id_proto_load";
+        break;
     case op_get_array_length:
         op = "array_length";
         break;
@@ -405,6 +409,8 @@
         out.printf(" llint(");
         dumpStructure(out, "struct", structure, ident);
         out.printf(")");
+        if (exec->interpreter()->getOpcodeID(instruction[0].u.opcode) == op_get_by_id_proto_load)
+            out.printf(" proto(%p)", instruction[6].u.pointer);
     }
 
 #if ENABLE(JIT)
@@ -1112,6 +1118,7 @@
             break;
         }
         case op_get_by_id:
+        case op_get_by_id_proto_load:
         case op_get_array_length: {
             printGetByIdOp(out, exec, location, it);
             printGetByIdCacheStatus(out, exec, location, stubInfos);
@@ -2798,14 +2805,14 @@
     for (size_t size = propertyAccessInstructions.size(), i = 0; i < size; ++i) {
         Instruction* curInstruction = &instructions()[propertyAccessInstructions[i]];
         switch (interpreter->getOpcodeID(curInstruction[0].u.opcode)) {
-        case op_get_by_id: {
+        case op_get_by_id:
+        case op_get_by_id_proto_load: {
             StructureID oldStructureID = curInstruction[4].u.structureID;
             if (!oldStructureID || Heap::isMarked(m_vm->heap.structureIDTable().get(oldStructureID)))
                 break;
             if (Options::verboseOSR())
                 dataLogF("Clearing LLInt property access.\n");
-            curInstruction[4].u.structureID = 0;
-            curInstruction[5].u.operand = 0;
+            clearLLIntGetByIdCache(curInstruction);
             break;
         }
         case op_put_by_id: {
@@ -2879,6 +2886,12 @@
         }
     }
 
+    // We can't just remove all the sets when we clear the caches since we might have created a watchpoint set
+    // then cleared the cache without GCing in between.
+    m_llintGetByIdWatchpointMap.removeIf([](const StructureWatchpointMap::KeyValuePairType& pair) -> bool {
+        return !Heap::isMarked(pair.key);
+    });
+
     for (unsigned i = 0; i < m_llintCallLinkInfos.size(); ++i) {
         if (m_llintCallLinkInfos[i].isLinked() && !Heap::isMarked(m_llintCallLinkInfos[i].callee.get())) {
             if (Options::verboseOSR())

Modified: trunk/Source/_javascript_Core/bytecode/CodeBlock.h (201362 => 201363)


--- trunk/Source/_javascript_Core/bytecode/CodeBlock.h	2016-05-24 23:09:54 UTC (rev 201362)
+++ trunk/Source/_javascript_Core/bytecode/CodeBlock.h	2016-05-24 23:49:57 UTC (rev 201363)
@@ -56,6 +56,7 @@
 #include "JSGlobalObject.h"
 #include "JumpTable.h"
 #include "LLIntCallLinkInfo.h"
+#include "LLIntPrototypeLoadAdaptiveStructureWatchpoint.h"
 #include "LazyOperandValueProfile.h"
 #include "ObjectAllocationProfile.h"
 #include "Options.h"
@@ -678,6 +679,9 @@
         return m_llintExecuteCounter;
     }
 
+    typedef HashMap<Structure*, Bag<LLIntPrototypeLoadAdaptiveStructureWatchpoint>> StructureWatchpointMap;
+    StructureWatchpointMap& llintGetByIdWatchpointMap() { return m_llintGetByIdWatchpointMap; }
+
     // Functions for controlling when tiered compilation kicks in. This
     // controls both when the optimizing compiler is invoked and when OSR
     // entry happens. Two triggers exist: the loop trigger and the return
@@ -1019,6 +1023,7 @@
 
     RefCountedArray<LLIntCallLinkInfo> m_llintCallLinkInfos;
     SentinelLinkedList<LLIntCallLinkInfo, BasicRawSentinelNode<LLIntCallLinkInfo>> m_incomingLLIntCalls;
+    StructureWatchpointMap m_llintGetByIdWatchpointMap;
     RefPtr<JITCode> m_jitCode;
 #if ENABLE(JIT)
     std::unique_ptr<RegisterAtOffsetList> m_calleeSaveRegisters;
@@ -1309,6 +1314,14 @@
 };
 #endif
 
+inline void clearLLIntGetByIdCache(Instruction* instruction)
+{
+    instruction[0].u.opcode = LLInt::getOpcode(op_get_by_id);
+    instruction[4].u.pointer = nullptr;
+    instruction[5].u.pointer = nullptr;
+    instruction[6].u.pointer = nullptr;
+}
+
 inline Register& ExecState::r(int index)
 {
     CodeBlock* codeBlock = this->codeBlock();

Modified: trunk/Source/_javascript_Core/bytecode/GetByIdStatus.cpp (201362 => 201363)


--- trunk/Source/_javascript_Core/bytecode/GetByIdStatus.cpp	2016-05-24 23:09:54 UTC (rev 201362)
+++ trunk/Source/_javascript_Core/bytecode/GetByIdStatus.cpp	2016-05-24 23:49:57 UTC (rev 201363)
@@ -75,8 +75,12 @@
     VM& vm = *profiledBlock->vm();
     
     Instruction* instruction = profiledBlock->instructions().begin() + bytecodeIndex;
-    
-    if (instruction[0].u.opcode == LLInt::getOpcode(op_get_array_length) || instruction[0].u.opcode == LLInt::getOpcode(op_try_get_by_id))
+
+    Opcode opcode = instruction[0].u.opcode;
+
+    // FIXME: We should not just bail if we see a try_get_by_id or a get_by_id_proto_load.
+    // https://bugs.webkit.org/show_bug.cgi?id=158039
+    if (opcode == LLInt::getOpcode(op_get_array_length) || opcode == LLInt::getOpcode(op_try_get_by_id) || opcode == LLInt::getOpcode(op_get_by_id_proto_load))
         return GetByIdStatus(NoInformation, false);
 
     StructureID structureID = instruction[4].u.structureID;

Added: trunk/Source/_javascript_Core/bytecode/LLIntPrototypeLoadAdaptiveStructureWatchpoint.cpp (0 => 201363)


--- trunk/Source/_javascript_Core/bytecode/LLIntPrototypeLoadAdaptiveStructureWatchpoint.cpp	                        (rev 0)
+++ trunk/Source/_javascript_Core/bytecode/LLIntPrototypeLoadAdaptiveStructureWatchpoint.cpp	2016-05-24 23:49:57 UTC (rev 201363)
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "LLIntPrototypeLoadAdaptiveStructureWatchpoint.h"
+
+#include "CodeBlock.h"
+#include "Instruction.h"
+#include "StructureInlines.h"
+
+namespace JSC {
+
+LLIntPrototypeLoadAdaptiveStructureWatchpoint::LLIntPrototypeLoadAdaptiveStructureWatchpoint(const ObjectPropertyCondition& key, Instruction* getByIdInstruction)
+    : m_key(key)
+    , m_getByIdInstruction(getByIdInstruction)
+{
+    RELEASE_ASSERT(key.watchingRequiresStructureTransitionWatchpoint());
+    RELEASE_ASSERT(!key.watchingRequiresReplacementWatchpoint());
+}
+
+void LLIntPrototypeLoadAdaptiveStructureWatchpoint::install()
+{
+    RELEASE_ASSERT(m_key.isWatchable());
+
+    m_key.object()->structure()->addTransitionWatchpoint(this);
+}
+
+void LLIntPrototypeLoadAdaptiveStructureWatchpoint::fireInternal(const FireDetail& detail)
+{
+    if (m_key.isWatchable(PropertyCondition::EnsureWatchability)) {
+        install();
+        return;
+    }
+
+    StringPrintStream out;
+    out.print("ObjectToStringValue Adaptation of ", m_key, " failed: ", detail);
+
+    StringFireDetail stringDetail(out.toCString().data());
+
+    clearLLIntGetByIdCache(m_getByIdInstruction);
+}
+
+} // namespace JSC

Added: trunk/Source/_javascript_Core/bytecode/LLIntPrototypeLoadAdaptiveStructureWatchpoint.h (0 => 201363)


--- trunk/Source/_javascript_Core/bytecode/LLIntPrototypeLoadAdaptiveStructureWatchpoint.h	                        (rev 0)
+++ trunk/Source/_javascript_Core/bytecode/LLIntPrototypeLoadAdaptiveStructureWatchpoint.h	2016-05-24 23:49:57 UTC (rev 201363)
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef LLIntPrototypeLoadAdaptiveStructureWatchpoint_h
+#define LLIntPrototypeLoadAdaptiveStructureWatchpoint_h
+
+#include "Instruction.h"
+#include "ObjectPropertyCondition.h"
+#include "Watchpoint.h"
+
+namespace JSC {
+
+class LLIntPrototypeLoadAdaptiveStructureWatchpoint : public Watchpoint {
+public:
+    LLIntPrototypeLoadAdaptiveStructureWatchpoint(const ObjectPropertyCondition&, Instruction*);
+
+    void install();
+
+protected:
+    void fireInternal(const FireDetail&) override;
+
+private:
+    ObjectPropertyCondition m_key;
+    Instruction* m_getByIdInstruction;
+};
+
+} // namespace JSC
+
+#endif /* LLIntPrototypeLoadAdaptiveStructureWatchpoint_h */

Modified: trunk/Source/_javascript_Core/bytecode/ObjectPropertyConditionSet.cpp (201362 => 201363)


--- trunk/Source/_javascript_Core/bytecode/ObjectPropertyConditionSet.cpp	2016-05-24 23:09:54 UTC (rev 201362)
+++ trunk/Source/_javascript_Core/bytecode/ObjectPropertyConditionSet.cpp	2016-05-24 23:49:57 UTC (rev 201363)
@@ -167,6 +167,18 @@
     dumpInContext(out, nullptr);
 }
 
+bool ObjectPropertyConditionSet::isValidAndWatchable() const
+{
+    if (!isValid())
+        return false;
+
+    for (ObjectPropertyCondition condition : m_data->vector) {
+        if (!condition.isWatchable())
+            return false;
+    }
+    return true;
+}
+
 namespace {
 
 bool verbose = false;
@@ -254,9 +266,11 @@
         // Since we're accessing a prototype repeatedly, it's a good bet that it should not be
         // treated as a dictionary.
         if (structure->isDictionary()) {
-            if (concurrency == MainThread)
+            if (concurrency == MainThread) {
+                if (verbose)
+                    dataLog("Flattening ", pointerDump(structure));
                 structure->flattenDictionaryStructure(vm, object);
-            else {
+            } else {
                 if (verbose)
                     dataLog("Cannot flatten dictionary when not on main thread, so invalid.\n");
                 return ObjectPropertyConditionSet::invalid();

Modified: trunk/Source/_javascript_Core/bytecode/ObjectPropertyConditionSet.h (201362 => 201363)


--- trunk/Source/_javascript_Core/bytecode/ObjectPropertyConditionSet.h	2016-05-24 23:09:54 UTC (rev 201362)
+++ trunk/Source/_javascript_Core/bytecode/ObjectPropertyConditionSet.h	2016-05-24 23:49:57 UTC (rev 201363)
@@ -67,6 +67,8 @@
     {
         return !m_data || !m_data->vector.isEmpty();
     }
+
+    bool isValidAndWatchable() const;
     
     bool isEmpty() const
     {

Modified: trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.cpp (201362 => 201363)


--- trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.cpp	2016-05-24 23:09:54 UTC (rev 201362)
+++ trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.cpp	2016-05-24 23:49:57 UTC (rev 201363)
@@ -2431,7 +2431,7 @@
     instructions().append(0);
     instructions().append(0);
     instructions().append(0);
-    instructions().append(0);
+    instructions().append(Options::prototypeHitCountForLLIntCaching());
     instructions().append(profile);
     return dst;
 }

Modified: trunk/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp (201362 => 201363)


--- trunk/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp	2016-05-24 23:09:54 UTC (rev 201362)
+++ trunk/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp	2016-05-24 23:49:57 UTC (rev 201363)
@@ -4081,6 +4081,7 @@
         }
 
         case op_get_by_id:
+        case op_get_by_id_proto_load:
         case op_get_array_length: {
             SpeculatedType prediction = getPrediction();
             

Modified: trunk/Source/_javascript_Core/dfg/DFGCapabilities.cpp (201362 => 201363)


--- trunk/Source/_javascript_Core/dfg/DFGCapabilities.cpp	2016-05-24 23:09:54 UTC (rev 201362)
+++ trunk/Source/_javascript_Core/dfg/DFGCapabilities.cpp	2016-05-24 23:49:57 UTC (rev 201363)
@@ -154,6 +154,7 @@
     case op_put_by_val_direct:
     case op_try_get_by_id:
     case op_get_by_id:
+    case op_get_by_id_proto_load:
     case op_get_by_id_with_this:
     case op_get_by_val_with_this:
     case op_get_array_length:

Modified: trunk/Source/_javascript_Core/jit/JIT.cpp (201362 => 201363)


--- trunk/Source/_javascript_Core/jit/JIT.cpp	2016-05-24 23:09:54 UTC (rev 201362)
+++ trunk/Source/_javascript_Core/jit/JIT.cpp	2016-05-24 23:49:57 UTC (rev 201363)
@@ -240,6 +240,7 @@
         DEFINE_OP(op_eq_null)
         DEFINE_OP(op_try_get_by_id)
         case op_get_array_length:
+        case op_get_by_id_proto_load:
         DEFINE_OP(op_get_by_id)
         DEFINE_OP(op_get_by_id_with_this)
         DEFINE_OP(op_get_by_val)
@@ -422,6 +423,7 @@
         DEFINE_SLOWCASE_OP(op_eq)
         DEFINE_SLOWCASE_OP(op_try_get_by_id)
         case op_get_array_length:
+        case op_get_by_id_proto_load:
         DEFINE_SLOWCASE_OP(op_get_by_id)
         DEFINE_SLOWCASE_OP(op_get_by_val)
         DEFINE_SLOWCASE_OP(op_instanceof)

Modified: trunk/Source/_javascript_Core/llint/LLIntSlowPaths.cpp (201362 => 201363)


--- trunk/Source/_javascript_Core/llint/LLIntSlowPaths.cpp	2016-05-24 23:09:54 UTC (rev 201362)
+++ trunk/Source/_javascript_Core/llint/LLIntSlowPaths.cpp	2016-05-24 23:49:57 UTC (rev 201363)
@@ -52,6 +52,7 @@
 #include "LLIntExceptions.h"
 #include "LowLevelInterpreter.h"
 #include "ObjectConstructor.h"
+#include "ObjectPropertyConditionSet.h"
 #include "ProtoCallFrame.h"
 #include "ShadowChicken.h"
 #include "StructureRareDataInlines.h"
@@ -580,6 +581,43 @@
     LLINT_RETURN(slot.getPureResult());
 }
 
+static void setupGetByIdPrototypeCache(ExecState* exec, VM& vm, Instruction* pc, JSCell* baseCell, PropertySlot& slot, const Identifier& ident)
+{
+    CodeBlock* codeBlock = exec->codeBlock();
+    Structure* structure = baseCell->structure();
+
+    if (structure->typeInfo().prohibitsPropertyCaching() || structure->isDictionary())
+        return;
+
+    ObjectPropertyConditionSet conditions = generateConditionsForPrototypePropertyHit(vm, codeBlock, exec, structure, slot.slotBase(), ident.impl());
+
+    if (!conditions.isValid())
+        return;
+
+    PropertyOffset offset = invalidOffset;
+    CodeBlock::StructureWatchpointMap& watchpointMap = codeBlock->llintGetByIdWatchpointMap();
+    auto result = watchpointMap.add(structure, Bag<LLIntPrototypeLoadAdaptiveStructureWatchpoint>());
+    for (ObjectPropertyCondition condition : conditions) {
+        if (!condition.isWatchable())
+            return;
+        if (condition.condition().kind() == PropertyCondition::Presence)
+            offset = condition.condition().offset();
+        result.iterator->value.add(condition, pc)->install();
+    }
+    ASSERT(offset != invalidOffset);
+
+    ConcurrentJITLocker locker(codeBlock->m_lock);
+
+    pc[0].u.opcode = LLInt::getOpcode(op_get_by_id_proto_load);
+    pc[4].u.structureID = structure->id();
+    pc[5].u.operand = offset;
+    // We know that this pointer will remain valid because it is the prototype of some structure, s,
+    // watchpointed above. If any object with structure s were to change prototypes then the conditions
+    // for this cache would fail and this value will never be used again.
+    pc[6].u.pointer = slot.slotBase();
+}
+
+
 LLINT_SLOW_PATH_DECL(slow_path_get_by_id)
 {
     LLINT_BEGIN();
@@ -594,37 +632,43 @@
     
     if (!LLINT_ALWAYS_ACCESS_SLOW
         && baseValue.isCell()
-        && slot.isCacheable()
-        && slot.slotBase() == baseValue
         && slot.isCacheableValue()) {
-        
+
         JSCell* baseCell = baseValue.asCell();
         Structure* structure = baseCell->structure();
+        if (slot.slotBase() == baseValue) {
+            // Start out by clearing out the old cache.
+            pc[0].u.opcode = LLInt::getOpcode(op_get_by_id);
+            pc[4].u.pointer = nullptr; // old structure
+            pc[5].u.pointer = nullptr; // offset
+
+            // Prevent the prototype cache from ever happening.
+            pc[7].u.operand = 0;
         
-        // Start out by clearing out the old cache.
-        pc[0].u.opcode = LLInt::getOpcode(op_get_by_id);
-        pc[4].u.pointer = nullptr; // old structure
-        pc[5].u.pointer = nullptr; // offset
-        
-        if (!structure->isUncacheableDictionary()
-            && !structure->typeInfo().prohibitsPropertyCaching()
-            && !structure->typeInfo().newImpurePropertyFiresWatchpoints()) {
-            vm.heap.writeBarrier(codeBlock);
-            
-            ConcurrentJITLocker locker(codeBlock->m_lock);
+            if (structure->propertyAccessesAreCacheable()) {
+                vm.heap.writeBarrier(codeBlock);
+                
+                ConcurrentJITLocker locker(codeBlock->m_lock);
 
-            pc[4].u.structureID = structure->id();
-            pc[5].u.operand = slot.cachedOffset();
+                pc[4].u.structureID = structure->id();
+                pc[5].u.operand = slot.cachedOffset();
+            }
+        } else if (UNLIKELY(pc[7].u.operand)) {
+            ASSERT(slot.slotBase() != baseValue);
+
+            if (!(--pc[7].u.operand))
+                setupGetByIdPrototypeCache(exec, vm, pc, baseCell, slot, ident);
         }
-    }
-
-    if (!LLINT_ALWAYS_ACCESS_SLOW
+    } else if (!LLINT_ALWAYS_ACCESS_SLOW
         && isJSArray(baseValue)
         && ident == exec->propertyNames().length) {
         pc[0].u.opcode = LLInt::getOpcode(op_get_array_length);
         ArrayProfile* arrayProfile = codeBlock->getOrAddArrayProfile(pc - codeBlock->instructions().begin());
         arrayProfile->observeStructure(baseValue.asCell()->structure());
         pc[4].u.arrayProfile = arrayProfile;
+
+        // Prevent the prototype cache from ever happening.
+        pc[7].u.operand = 0;
     }
 
     pc[OPCODE_LENGTH(op_get_by_id) - 1].u.profile->m_buckets[0] = JSValue::encode(result);

Modified: trunk/Source/_javascript_Core/llint/LLIntSlowPaths.h (201362 => 201363)


--- trunk/Source/_javascript_Core/llint/LLIntSlowPaths.h	2016-05-24 23:09:54 UTC (rev 201362)
+++ trunk/Source/_javascript_Core/llint/LLIntSlowPaths.h	2016-05-24 23:49:57 UTC (rev 201363)
@@ -71,6 +71,7 @@
 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_by_id_proto_load);
 LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_get_arguments_length);
 LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_put_by_id);
 LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_del_by_id);

Modified: trunk/Source/_javascript_Core/llint/LowLevelInterpreter32_64.asm (201362 => 201363)


--- trunk/Source/_javascript_Core/llint/LowLevelInterpreter32_64.asm	2016-05-24 23:09:54 UTC (rev 201362)
+++ trunk/Source/_javascript_Core/llint/LowLevelInterpreter32_64.asm	2016-05-24 23:49:57 UTC (rev 201363)
@@ -1334,10 +1334,11 @@
 
 
 # We only do monomorphic get_by_id caching for now, and we do not modify the
-# opcode. We do, however, allow for the cache to change anytime if fails, since
-# ping-ponging is free. At best we get lucky and the get_by_id will continue
+# opcode for own properties. We also allow for the cache to change anytime it fails,
+# since ping-ponging is free. At best we get lucky and the get_by_id will continue
 # to take fast path on the new cache. At worst we take slow path, which is what
-# we would have been doing anyway.
+# we would have been doing anyway. For prototype properties, we will attempt to
+# convert opcode into a get_by_id_proto_load after a execution counter hits zero.
 
 _llint_op_get_by_id:
     traceExecution()
@@ -1358,6 +1359,27 @@
     dispatch(9)
 
 
+
+_llint_op_get_by_id_proto_load:
+    traceExecution()
+    loadi 8[PC], t0
+    loadi 16[PC], t1
+    loadConstantOrVariablePayload(t0, CellTag, t3, .opGetByIdProtoSlow)
+    loadi 20[PC], t2
+    bineq JSCell::m_structureID[t3], t1, .opGetByIdProtoSlow
+    loadpFromInstruction(6, t3)
+    loadPropertyAtVariableOffset(t2, t3, t0, t1)
+    loadi 4[PC], t2
+    storei t0, TagOffset[cfr, t2, 8]
+    storei t1, PayloadOffset[cfr, t2, 8]
+    valueProfile(t0, t1, 32, t2)
+    dispatch(9)
+
+.opGetByIdProtoSlow:
+    callSlowPath(_llint_slow_path_get_by_id)
+    dispatch(9)
+
+
 _llint_op_get_array_length:
     traceExecution()
     loadi 8[PC], t0

Modified: trunk/Source/_javascript_Core/llint/LowLevelInterpreter64.asm (201362 => 201363)


--- trunk/Source/_javascript_Core/llint/LowLevelInterpreter64.asm	2016-05-24 23:09:54 UTC (rev 201362)
+++ trunk/Source/_javascript_Core/llint/LowLevelInterpreter64.asm	2016-05-24 23:49:57 UTC (rev 201363)
@@ -1232,6 +1232,26 @@
     dispatch(9)
 
 
+_llint_op_get_by_id_proto_load:
+    traceExecution()
+    loadisFromInstruction(2, t0)
+    loadConstantOrVariableCell(t0, t3, .opGetByIdProtoSlow)
+    loadi JSCell::m_structureID[t3], t1
+    loadisFromInstruction(4, t2)
+    bineq t2, t1, .opGetByIdProtoSlow
+    loadisFromInstruction(5, t1)
+    loadpFromInstruction(6, t3)
+    loadisFromInstruction(1, t2)
+    loadPropertyAtVariableOffset(t1, t3, t0)
+    storeq t0, [cfr, t2, 8]
+    valueProfile(t0, 8, t1)
+    dispatch(9)
+
+.opGetByIdProtoSlow:
+    callSlowPath(_llint_slow_path_get_by_id)
+    dispatch(9)
+
+
 _llint_op_get_array_length:
     traceExecution()
     loadisFromInstruction(2, t0)

Modified: trunk/Source/_javascript_Core/runtime/Options.h (201362 => 201363)


--- trunk/Source/_javascript_Core/runtime/Options.h	2016-05-24 23:09:54 UTC (rev 201362)
+++ trunk/Source/_javascript_Core/runtime/Options.h	2016-05-24 23:49:57 UTC (rev 201363)
@@ -362,6 +362,8 @@
     \
     v(bool, useICStats, false, Normal, nullptr) \
     \
+    v(unsigned, prototypeHitCountForLLIntCaching, 2, Normal, "Number of prototype property hits before caching a prototype in the LLInt. A count of 0 means never cache.") \
+    \
     v(bool, dumpModuleRecord, false, Normal, nullptr) \
     v(bool, dumpModuleLoadingState, false, Normal, nullptr) \
     v(bool, exposeInternalModuleLoader, false, Normal, "expose the internal module loader object to the global space for debugging") \

Added: trunk/Source/_javascript_Core/tests/stress/llint-get-by-id-cache-prototype-load-from-dictionary.js (0 => 201363)


--- trunk/Source/_javascript_Core/tests/stress/llint-get-by-id-cache-prototype-load-from-dictionary.js	                        (rev 0)
+++ trunk/Source/_javascript_Core/tests/stress/llint-get-by-id-cache-prototype-load-from-dictionary.js	2016-05-24 23:49:57 UTC (rev 201363)
@@ -0,0 +1,19 @@
+
+expected = Object.prototype.toString;
+foo = {foo: 1, bar: 20};
+delete foo.bar;
+
+
+function test() {
+    let toString = foo.toString;
+    if (toString !== expected)
+        throw new Error();
+}
+
+for (i = 0; i < 10; i++)
+    test();
+
+foo.toString = 100;
+expected = 100;
+
+test();

Modified: trunk/Source/WTF/ChangeLog (201362 => 201363)


--- trunk/Source/WTF/ChangeLog	2016-05-24 23:09:54 UTC (rev 201362)
+++ trunk/Source/WTF/ChangeLog	2016-05-24 23:49:57 UTC (rev 201363)
@@ -1,3 +1,16 @@
+2016-05-24  Keith Miller  <[email protected]>
+
+        LLInt should be able to cache prototype loads for values in GetById
+        https://bugs.webkit.org/show_bug.cgi?id=158032
+
+        Reviewed by Filip Pizlo.
+
+        Add move constructors/initializers to Bags.
+
+        * wtf/Bag.h:
+        (WTF::Bag::Bag):
+        (WTF::Bag::operator=):
+
 2016-05-24  Chris Dumez  <[email protected]>
 
         Use auto for some of our lambda function parameters

Modified: trunk/Source/WTF/wtf/Bag.h (201362 => 201363)


--- trunk/Source/WTF/wtf/Bag.h	2016-05-24 23:09:54 UTC (rev 201362)
+++ trunk/Source/WTF/wtf/Bag.h	2016-05-24 23:49:57 UTC (rev 201363)
@@ -48,9 +48,22 @@
     
 public:
     Bag()
-        : m_head(nullptr)
     {
     }
+
+    Bag(Bag<T>&& other)
+    {
+        ASSERT(!m_head);
+        m_head = other.m_head;
+        other.m_head = nullptr;
+    }
+
+    Bag& operator=(Bag<T>&& other)
+    {
+        m_head = other.m_head;
+        other.m_head = nullptr;
+        return *this;
+    }
     
     ~Bag()
     {
@@ -121,7 +134,7 @@
     bool isEmpty() const { return !m_head; }
     
 private:
-    Node* m_head;
+    Node* m_head { nullptr };
 };
 
 } // namespace WTF
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to