Object properties added using dot syntax (o.f = ...) from code that isn't in eval...
authorfpizlo@apple.com <fpizlo@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 16 Aug 2013 19:15:31 +0000 (19:15 +0000)
committerfpizlo@apple.com <fpizlo@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 16 Aug 2013 19:15:31 +0000 (19:15 +0000)
https://bugs.webkit.org/show_bug.cgi?id=119897

Source/JavaScriptCore:

Reviewed by Oliver Hunt.

6-10x speed-up on microbenchmarks that create large static objects. 40-65% speed-up
on Octane/gbemu. 3% overall speed-up on Octane. No slow-downs anywhere; our ability
to turn objects into dictionaries when you're storing using bracket syntax or using
eval is still in place.

* bytecode/CodeBlock.h:
(JSC::CodeBlock::putByIdContext):
* dfg/DFGOperations.cpp:
* jit/JITStubs.cpp:
(JSC::DEFINE_STUB_FUNCTION):
* llint/LLIntSlowPaths.cpp:
(JSC::LLInt::LLINT_SLOW_PATH_DECL):
* runtime/JSObject.h:
(JSC::JSObject::putDirectInternal):
* runtime/PutPropertySlot.h:
(JSC::PutPropertySlot::PutPropertySlot):
(JSC::PutPropertySlot::context):
* runtime/Structure.cpp:
(JSC::Structure::addPropertyTransition):
* runtime/Structure.h:

LayoutTests:

Reviewed by Oliver Hunt.

* fast/js/regress/lots-of-fields-expected.txt: Added.
* fast/js/regress/lots-of-fields.html: Added.
* fast/js/regress/script-tests/lots-of-fields.js: Added.
(foo):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@154199 268f45cc-cd09-0410-ab3c-d52691b4dbfc

13 files changed:
LayoutTests/ChangeLog
LayoutTests/fast/js/regress/lots-of-fields-expected.txt [new file with mode: 0644]
LayoutTests/fast/js/regress/lots-of-fields.html [new file with mode: 0644]
LayoutTests/fast/js/regress/script-tests/lots-of-fields.js [new file with mode: 0644]
Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/bytecode/CodeBlock.h
Source/JavaScriptCore/dfg/DFGOperations.cpp
Source/JavaScriptCore/jit/JITStubs.cpp
Source/JavaScriptCore/llint/LLIntSlowPaths.cpp
Source/JavaScriptCore/runtime/JSObject.h
Source/JavaScriptCore/runtime/PutPropertySlot.h
Source/JavaScriptCore/runtime/Structure.cpp
Source/JavaScriptCore/runtime/Structure.h

index d0ba8e2..0bd2b20 100644 (file)
@@ -1,3 +1,15 @@
+2013-08-16  Filip Pizlo  <fpizlo@apple.com>
+
+        Object properties added using dot syntax (o.f = ...) from code that isn't in eval should be less likely to cause an object to become a dictionary
+        https://bugs.webkit.org/show_bug.cgi?id=119897
+
+        Reviewed by Oliver Hunt.
+
+        * fast/js/regress/lots-of-fields-expected.txt: Added.
+        * fast/js/regress/lots-of-fields.html: Added.
+        * fast/js/regress/script-tests/lots-of-fields.js: Added.
+        (foo):
+
 2013-08-16  Jer Noble  <jer.noble@apple.com>
 
         [Mac] Unreviewed gardening. Rebaseline after r154124.
diff --git a/LayoutTests/fast/js/regress/lots-of-fields-expected.txt b/LayoutTests/fast/js/regress/lots-of-fields-expected.txt
new file mode 100644 (file)
index 0000000..e64685e
--- /dev/null
@@ -0,0 +1,10 @@
+JSRegress/lots-of-fields
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS no exception thrown
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/fast/js/regress/lots-of-fields.html b/LayoutTests/fast/js/regress/lots-of-fields.html
new file mode 100644 (file)
index 0000000..44b527e
--- /dev/null
@@ -0,0 +1,12 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<script src="../resources/js-test-pre.js"></script>
+</head>
+<body>
+<script src="resources/regress-pre.js"></script>
+<script src="script-tests/lots-of-fields.js"></script>
+<script src="resources/regress-post.js"></script>
+<script src="../resources/js-test-post.js"></script>
+</body>
+</html>
diff --git a/LayoutTests/fast/js/regress/script-tests/lots-of-fields.js b/LayoutTests/fast/js/regress/script-tests/lots-of-fields.js
new file mode 100644 (file)
index 0000000..c3d1ea4
--- /dev/null
@@ -0,0 +1,213 @@
+function foo() {
+    var result = 0;
+    for (var i = 0; i < 5000; ++i) {
+        var o = {};
+        o.i0 = 0;
+        o.i1 = 1;
+        o.i2 = 2;
+        o.i3 = 3;
+        o.i4 = 4;
+        o.i5 = 5;
+        o.i6 = 6;
+        o.i7 = 7;
+        o.i8 = 8;
+        o.i9 = 9;
+        o.i10 = 10;
+        o.i11 = 11;
+        o.i12 = 12;
+        o.i13 = 13;
+        o.i14 = 14;
+        o.i15 = 15;
+        o.i16 = 16;
+        o.i17 = 17;
+        o.i18 = 18;
+        o.i19 = 19;
+        o.i20 = 20;
+        o.i21 = 21;
+        o.i22 = 22;
+        o.i23 = 23;
+        o.i24 = 24;
+        o.i25 = 25;
+        o.i26 = 26;
+        o.i27 = 27;
+        o.i28 = 28;
+        o.i29 = 29;
+        o.i30 = 30;
+        o.i31 = 31;
+        o.i32 = 32;
+        o.i33 = 33;
+        o.i34 = 34;
+        o.i35 = 35;
+        o.i36 = 36;
+        o.i37 = 37;
+        o.i38 = 38;
+        o.i39 = 39;
+        o.i40 = 40;
+        o.i41 = 41;
+        o.i42 = 42;
+        o.i43 = 43;
+        o.i44 = 44;
+        o.i45 = 45;
+        o.i46 = 46;
+        o.i47 = 47;
+        o.i48 = 48;
+        o.i49 = 49;
+        o.i50 = 50;
+        o.i51 = 51;
+        o.i52 = 52;
+        o.i53 = 53;
+        o.i54 = 54;
+        o.i55 = 55;
+        o.i56 = 56;
+        o.i57 = 57;
+        o.i58 = 58;
+        o.i59 = 59;
+        o.i60 = 60;
+        o.i61 = 61;
+        o.i62 = 62;
+        o.i63 = 63;
+        o.i64 = 64;
+        o.i65 = 65;
+        o.i66 = 66;
+        o.i67 = 67;
+        o.i68 = 68;
+        o.i69 = 69;
+        o.i70 = 70;
+        o.i71 = 71;
+        o.i72 = 72;
+        o.i73 = 73;
+        o.i74 = 74;
+        o.i75 = 75;
+        o.i76 = 76;
+        o.i77 = 77;
+        o.i78 = 78;
+        o.i79 = 79;
+        o.i80 = 80;
+        o.i81 = 81;
+        o.i82 = 82;
+        o.i83 = 83;
+        o.i84 = 84;
+        o.i85 = 85;
+        o.i86 = 86;
+        o.i87 = 87;
+        o.i88 = 88;
+        o.i89 = 89;
+        o.i90 = 90;
+        o.i91 = 91;
+        o.i92 = 92;
+        o.i93 = 93;
+        o.i94 = 94;
+        o.i95 = 95;
+        o.i96 = 96;
+        o.i97 = 97;
+        o.i98 = 98;
+        o.i99 = 99;
+        o.i100 = 100;
+        o.i101 = 101;
+        o.i102 = 102;
+        o.i103 = 103;
+        o.i104 = 104;
+        o.i105 = 105;
+        o.i106 = 106;
+        o.i107 = 107;
+        o.i108 = 108;
+        o.i109 = 109;
+        o.i110 = 110;
+        o.i111 = 111;
+        o.i112 = 112;
+        o.i113 = 113;
+        o.i114 = 114;
+        o.i115 = 115;
+        o.i116 = 116;
+        o.i117 = 117;
+        o.i118 = 118;
+        o.i119 = 119;
+        o.i120 = 120;
+        o.i121 = 121;
+        o.i122 = 122;
+        o.i123 = 123;
+        o.i124 = 124;
+        o.i125 = 125;
+        o.i126 = 126;
+        o.i127 = 127;
+        o.i128 = 128;
+        o.i129 = 129;
+        o.i130 = 130;
+        o.i131 = 131;
+        o.i132 = 132;
+        o.i133 = 133;
+        o.i134 = 134;
+        o.i135 = 135;
+        o.i136 = 136;
+        o.i137 = 137;
+        o.i138 = 138;
+        o.i139 = 139;
+        o.i140 = 140;
+        o.i141 = 141;
+        o.i142 = 142;
+        o.i143 = 143;
+        o.i144 = 144;
+        o.i145 = 145;
+        o.i146 = 146;
+        o.i147 = 147;
+        o.i148 = 148;
+        o.i149 = 149;
+        o.i150 = 150;
+        o.i151 = 151;
+        o.i152 = 152;
+        o.i153 = 153;
+        o.i154 = 154;
+        o.i155 = 155;
+        o.i156 = 156;
+        o.i157 = 157;
+        o.i158 = 158;
+        o.i159 = 159;
+        o.i160 = 160;
+        o.i161 = 161;
+        o.i162 = 162;
+        o.i163 = 163;
+        o.i164 = 164;
+        o.i165 = 165;
+        o.i166 = 166;
+        o.i167 = 167;
+        o.i168 = 168;
+        o.i169 = 169;
+        o.i170 = 170;
+        o.i171 = 171;
+        o.i172 = 172;
+        o.i173 = 173;
+        o.i174 = 174;
+        o.i175 = 175;
+        o.i176 = 176;
+        o.i177 = 177;
+        o.i178 = 178;
+        o.i179 = 179;
+        o.i180 = 180;
+        o.i181 = 181;
+        o.i182 = 182;
+        o.i183 = 183;
+        o.i184 = 184;
+        o.i185 = 185;
+        o.i186 = 186;
+        o.i187 = 187;
+        o.i188 = 188;
+        o.i189 = 189;
+        o.i190 = 190;
+        o.i191 = 191;
+        o.i192 = 192;
+        o.i193 = 193;
+        o.i194 = 194;
+        o.i195 = 195;
+        o.i196 = 196;
+        o.i197 = 197;
+        o.i198 = 198;
+        o.i199 = 199;
+        for (var j = 0; j < 100; ++j)
+            result += o.i100;
+    }
+    return result;
+}
+
+var result = foo();
+if (result != 50000000)
+    throw "Error: bad result: " + result;
index 7c84777..d2fb683 100644 (file)
@@ -1,3 +1,31 @@
+2013-08-16  Filip Pizlo  <fpizlo@apple.com>
+
+        Object properties added using dot syntax (o.f = ...) from code that isn't in eval should be less likely to cause an object to become a dictionary
+        https://bugs.webkit.org/show_bug.cgi?id=119897
+
+        Reviewed by Oliver Hunt.
+        
+        6-10x speed-up on microbenchmarks that create large static objects. 40-65% speed-up
+        on Octane/gbemu. 3% overall speed-up on Octane. No slow-downs anywhere; our ability
+        to turn objects into dictionaries when you're storing using bracket syntax or using
+        eval is still in place.
+
+        * bytecode/CodeBlock.h:
+        (JSC::CodeBlock::putByIdContext):
+        * dfg/DFGOperations.cpp:
+        * jit/JITStubs.cpp:
+        (JSC::DEFINE_STUB_FUNCTION):
+        * llint/LLIntSlowPaths.cpp:
+        (JSC::LLInt::LLINT_SLOW_PATH_DECL):
+        * runtime/JSObject.h:
+        (JSC::JSObject::putDirectInternal):
+        * runtime/PutPropertySlot.h:
+        (JSC::PutPropertySlot::PutPropertySlot):
+        (JSC::PutPropertySlot::context):
+        * runtime/Structure.cpp:
+        (JSC::Structure::addPropertyTransition):
+        * runtime/Structure.h:
+
 2013-08-16  Balazs Kilvady  <kilvadyb@homejinni.com>
 
         <https://webkit.org/b/119742> REGRESSION(FTL): Fix register usage in mips implementation of ctiVMHandleException
index bdf710b..a839b7f 100644 (file)
@@ -55,6 +55,7 @@
 #include "ObjectAllocationProfile.h"
 #include "Options.h"
 #include "Operations.h"
+#include "PutPropertySlot.h"
 #include "Instruction.h"
 #include "JITCode.h"
 #include "JITWriteBarrier.h"
@@ -398,6 +399,12 @@ public:
     }
 
     CodeType codeType() const { return m_unlinkedCode->codeType(); }
+    PutPropertySlot::Context putByIdContext() const
+    {
+        if (codeType() == EvalCode)
+            return PutPropertySlot::PutByIdEval;
+        return PutPropertySlot::PutById;
+    }
 
     SourceProvider* source() const { return m_source.get(); }
     unsigned sourceOffset() const { return m_sourceOffset; }
index d254ffb..39516de 100644 (file)
@@ -832,7 +832,7 @@ void DFG_OPERATION operationPutByIdStrict(ExecState* exec, EncodedJSValue encode
     NativeCallFrameTracer tracer(vm, exec);
     
     Identifier ident(vm, uid);
-    PutPropertySlot slot(true);
+    PutPropertySlot slot(true, exec->codeBlock()->putByIdContext());
     base->methodTable()->put(base, exec, ident, JSValue::decode(encodedValue), slot);
 }
 
@@ -842,7 +842,7 @@ void DFG_OPERATION operationPutByIdNonStrict(ExecState* exec, EncodedJSValue enc
     NativeCallFrameTracer tracer(vm, exec);
     
     Identifier ident(vm, uid);
-    PutPropertySlot slot(false);
+    PutPropertySlot slot(false, exec->codeBlock()->putByIdContext());
     base->methodTable()->put(base, exec, ident, JSValue::decode(encodedValue), slot);
 }
 
@@ -852,7 +852,7 @@ void DFG_OPERATION operationPutByIdDirectStrict(ExecState* exec, EncodedJSValue
     NativeCallFrameTracer tracer(vm, exec);
     
     Identifier ident(vm, uid);
-    PutPropertySlot slot(true);
+    PutPropertySlot slot(true, exec->codeBlock()->putByIdContext());
     ASSERT(base->isObject());
     asObject(base)->putDirect(exec->vm(), ident, JSValue::decode(encodedValue), slot);
 }
@@ -863,7 +863,7 @@ void DFG_OPERATION operationPutByIdDirectNonStrict(ExecState* exec, EncodedJSVal
     NativeCallFrameTracer tracer(vm, exec);
     
     Identifier ident(vm, uid);
-    PutPropertySlot slot(false);
+    PutPropertySlot slot(false, exec->codeBlock()->putByIdContext());
     ASSERT(base->isObject());
     asObject(base)->putDirect(exec->vm(), ident, JSValue::decode(encodedValue), slot);
 }
@@ -880,7 +880,7 @@ void DFG_OPERATION operationPutByIdStrictOptimizeWithReturnAddress(ExecState* ex
 
     JSValue value = JSValue::decode(encodedValue);
     JSValue baseValue(base);
-    PutPropertySlot slot(true);
+    PutPropertySlot slot(true, exec->codeBlock()->putByIdContext());
     
     baseValue.put(exec, ident, value, slot);
     
@@ -905,7 +905,7 @@ void DFG_OPERATION operationPutByIdNonStrictOptimizeWithReturnAddress(ExecState*
 
     JSValue value = JSValue::decode(encodedValue);
     JSValue baseValue(base);
-    PutPropertySlot slot(false);
+    PutPropertySlot slot(false, exec->codeBlock()->putByIdContext());
     
     baseValue.put(exec, ident, value, slot);
     
@@ -929,7 +929,7 @@ void DFG_OPERATION operationPutByIdDirectStrictOptimizeWithReturnAddress(ExecSta
     AccessType accessType = static_cast<AccessType>(stubInfo.accessType);
 
     JSValue value = JSValue::decode(encodedValue);
-    PutPropertySlot slot(true);
+    PutPropertySlot slot(true, exec->codeBlock()->putByIdContext());
     
     ASSERT(base->isObject());
     asObject(base)->putDirect(exec->vm(), ident, value, slot);
@@ -954,7 +954,7 @@ void DFG_OPERATION operationPutByIdDirectNonStrictOptimizeWithReturnAddress(Exec
     AccessType accessType = static_cast<AccessType>(stubInfo.accessType);
 
     JSValue value = JSValue::decode(encodedValue);
-    PutPropertySlot slot(false);
+    PutPropertySlot slot(false, exec->codeBlock()->putByIdContext());
     
     ASSERT(base->isObject());
     asObject(base)->putDirect(exec->vm(), ident, value, slot);
@@ -980,7 +980,7 @@ void DFG_OPERATION operationPutByIdStrictBuildListWithReturnAddress(ExecState* e
 
     JSValue value = JSValue::decode(encodedValue);
     JSValue baseValue(base);
-    PutPropertySlot slot(true);
+    PutPropertySlot slot(true, exec->codeBlock()->putByIdContext());
     
     baseValue.put(exec, ident, value, slot);
     
@@ -1002,7 +1002,7 @@ void DFG_OPERATION operationPutByIdNonStrictBuildListWithReturnAddress(ExecState
 
     JSValue value = JSValue::decode(encodedValue);
     JSValue baseValue(base);
-    PutPropertySlot slot(false);
+    PutPropertySlot slot(false, exec->codeBlock()->putByIdContext());
     
     baseValue.put(exec, ident, value, slot);
     
@@ -1023,7 +1023,7 @@ void DFG_OPERATION operationPutByIdDirectStrictBuildListWithReturnAddress(ExecSt
     AccessType accessType = static_cast<AccessType>(stubInfo.accessType);
     
     JSValue value = JSValue::decode(encodedValue);
-    PutPropertySlot slot(true);
+    PutPropertySlot slot(true, exec->codeBlock()->putByIdContext());
     
     ASSERT(base->isObject());
     asObject(base)->putDirect(exec->vm(), ident, value, slot);
@@ -1045,7 +1045,7 @@ void DFG_OPERATION operationPutByIdDirectNonStrictBuildListWithReturnAddress(Exe
     AccessType accessType = static_cast<AccessType>(stubInfo.accessType);
 
     JSValue value = JSValue::decode(encodedValue);
-    PutPropertySlot slot(false);
+    PutPropertySlot slot(false, exec->codeBlock()->putByIdContext());
     
     ASSERT(base->isObject());
     asObject(base)->putDirect(exec->vm(), ident, value, slot);
index f764110..702c4d5 100644 (file)
@@ -475,7 +475,9 @@ DEFINE_STUB_FUNCTION(void, op_put_by_id_generic)
 {
     STUB_INIT_STACK_FRAME(stackFrame);
 
-    PutPropertySlot slot(stackFrame.callFrame->codeBlock()->isStrictMode());
+    PutPropertySlot slot(
+        stackFrame.callFrame->codeBlock()->isStrictMode(),
+        stackFrame.callFrame->codeBlock()->putByIdContext());
     stackFrame.args[0].jsValue().put(stackFrame.callFrame, stackFrame.args[1].identifier(), stackFrame.args[2].jsValue(), slot);
     CHECK_FOR_EXCEPTION_AT_END();
 }
@@ -484,7 +486,9 @@ DEFINE_STUB_FUNCTION(void, op_put_by_id_direct_generic)
 {
     STUB_INIT_STACK_FRAME(stackFrame);
     
-    PutPropertySlot slot(stackFrame.callFrame->codeBlock()->isStrictMode());
+    PutPropertySlot slot(
+        stackFrame.callFrame->codeBlock()->isStrictMode(),
+        stackFrame.callFrame->codeBlock()->putByIdContext());
     JSValue baseValue = stackFrame.args[0].jsValue();
     ASSERT(baseValue.isObject());
     asObject(baseValue)->putDirect(stackFrame.callFrame->vm(), stackFrame.args[1].identifier(), stackFrame.args[2].jsValue(), slot);
@@ -516,7 +520,9 @@ DEFINE_STUB_FUNCTION(void, op_put_by_id)
     StructureStubInfo* stubInfo = &codeBlock->getStubInfo(STUB_RETURN_ADDRESS);
     AccessType accessType = static_cast<AccessType>(stubInfo->accessType);
 
-    PutPropertySlot slot(callFrame->codeBlock()->isStrictMode());
+    PutPropertySlot slot(
+        callFrame->codeBlock()->isStrictMode(),
+        callFrame->codeBlock()->putByIdContext());
     stackFrame.args[0].jsValue().put(callFrame, ident, stackFrame.args[2].jsValue(), slot);
     
     if (accessType == static_cast<AccessType>(stubInfo->accessType)) {
@@ -537,7 +543,9 @@ DEFINE_STUB_FUNCTION(void, op_put_by_id_direct)
     StructureStubInfo* stubInfo = &codeBlock->getStubInfo(STUB_RETURN_ADDRESS);
     AccessType accessType = static_cast<AccessType>(stubInfo->accessType);
 
-    PutPropertySlot slot(callFrame->codeBlock()->isStrictMode());
+    PutPropertySlot slot(
+        callFrame->codeBlock()->isStrictMode(),
+        callFrame->codeBlock()->putByIdContext());
     JSValue baseValue = stackFrame.args[0].jsValue();
     ASSERT(baseValue.isObject());
     
@@ -558,7 +566,9 @@ DEFINE_STUB_FUNCTION(void, op_put_by_id_fail)
     CallFrame* callFrame = stackFrame.callFrame;
     Identifier& ident = stackFrame.args[1].identifier();
     
-    PutPropertySlot slot(callFrame->codeBlock()->isStrictMode());
+    PutPropertySlot slot(
+        callFrame->codeBlock()->isStrictMode(),
+        callFrame->codeBlock()->putByIdContext());
     stackFrame.args[0].jsValue().put(callFrame, ident, stackFrame.args[2].jsValue(), slot);
 
     CHECK_FOR_EXCEPTION_AT_END();
@@ -571,7 +581,9 @@ DEFINE_STUB_FUNCTION(void, op_put_by_id_direct_fail)
     CallFrame* callFrame = stackFrame.callFrame;
     Identifier& ident = stackFrame.args[1].identifier();
     
-    PutPropertySlot slot(callFrame->codeBlock()->isStrictMode());
+    PutPropertySlot slot(
+        callFrame->codeBlock()->isStrictMode(),
+        callFrame->codeBlock()->putByIdContext());
     JSValue baseValue = stackFrame.args[0].jsValue();
     ASSERT(baseValue.isObject());
     asObject(baseValue)->putDirect(callFrame->vm(), ident, stackFrame.args[2].jsValue(), slot);
index fff9ca4..d6d0675 100644 (file)
@@ -570,7 +570,7 @@ LLINT_SLOW_PATH_DECL(slow_path_put_by_id)
     const Identifier& ident = codeBlock->identifier(pc[2].u.operand);
     
     JSValue baseValue = LLINT_OP_C(1).jsValue();
-    PutPropertySlot slot(codeBlock->isStrictMode());
+    PutPropertySlot slot(codeBlock->isStrictMode(), codeBlock->putByIdContext());
     if (pc[8].u.operand)
         asObject(baseValue)->putDirect(vm, ident, LLINT_OP_C(3).jsValue(), slot);
     else
index 9c66a13..61753f8 100644 (file)
@@ -1347,7 +1347,7 @@ inline bool JSObject::putDirectInternal(VM& vm, PropertyName propertyName, JSVal
     if ((mode == PutModePut) && !isExtensible())
         return false;
 
-    Structure* structure = Structure::addPropertyTransition(vm, this->structure(), propertyName, attributes, specificFunction, offset);
+    Structure* structure = Structure::addPropertyTransition(vm, this->structure(), propertyName, attributes, specificFunction, offset, slot.context());
     
     validateOffset(offset);
     ASSERT(structure->isValidOffset(offset));
index 0f694e3..421a9ce 100644 (file)
@@ -37,11 +37,13 @@ namespace JSC {
     class PutPropertySlot {
     public:
         enum Type { Uncachable, ExistingProperty, NewProperty };
+        enum Context { UnknownContext, PutById, PutByIdEval };
 
-        PutPropertySlot(bool isStrictMode = false)
+        PutPropertySlot(bool isStrictMode = false, Context context = UnknownContext)
             : m_type(Uncachable)
             , m_base(0)
             , m_isStrictMode(isStrictMode)
+            , m_context(context)
         {
         }
 
@@ -58,6 +60,8 @@ namespace JSC {
             m_base = base;
             m_offset = offset;
         }
+        
+        Context context() const { return static_cast<Context>(m_context); }
 
         Type type() const { return m_type; }
         JSObject* base() const { return m_base; }
@@ -75,6 +79,7 @@ namespace JSC {
         JSObject* m_base;
         PropertyOffset m_offset;
         bool m_isStrictMode;
+        uint8_t m_context;
     };
 
 } // namespace JSC
index 97b38d9..bcbeec7 100644 (file)
@@ -380,7 +380,7 @@ NonPropertyTransition Structure::suggestedArrayStorageTransition() const
     return AllocateArrayStorage;
 }
 
-Structure* Structure::addPropertyTransition(VM& vm, Structure* structure, PropertyName propertyName, unsigned attributes, JSCell* specificValue, PropertyOffset& offset)
+Structure* Structure::addPropertyTransition(VM& vm, Structure* structure, PropertyName propertyName, unsigned attributes, JSCell* specificValue, PropertyOffset& offset, PutPropertySlot::Context context)
 {
     // If we have a specific function, we may have got to this point if there is
     // already a transition with the correct property name and attributes, but
@@ -399,7 +399,12 @@ Structure* Structure::addPropertyTransition(VM& vm, Structure* structure, Proper
     if (structure->m_specificFunctionThrashCount == maxSpecificFunctionThrashCount)
         specificValue = 0;
 
-    if (structure->transitionCount() > s_maxTransitionLength) {
+    int maxTransitionLength;
+    if (context == PutPropertySlot::PutById)
+        maxTransitionLength = s_maxTransitionLengthForNonEvalPutById;
+    else
+        maxTransitionLength = s_maxTransitionLength;
+    if (structure->transitionCount() > maxTransitionLength) {
         Structure* transition = toCacheableDictionaryTransition(vm, structure);
         ASSERT(structure != transition);
         offset = transition->putSpecificValue(vm, propertyName, attributes, specificValue);
index 7ff7974..8d77ce7 100644 (file)
@@ -36,6 +36,7 @@
 #include "PropertyNameArray.h"
 #include "PropertyOffset.h"
 #include "Protect.h"
+#include "PutPropertySlot.h"
 #include "StructureRareData.h"
 #include "StructureTransitionTable.h"
 #include "JSTypeInfo.h"
@@ -95,7 +96,7 @@ protected:
 public:
     static void dumpStatistics();
 
-    JS_EXPORT_PRIVATE static Structure* addPropertyTransition(VM&, Structure*, PropertyName, unsigned attributes, JSCell* specificValue, PropertyOffset&);
+    JS_EXPORT_PRIVATE static Structure* addPropertyTransition(VM&, Structure*, PropertyName, unsigned attributes, JSCell* specificValue, PropertyOffset&, PutPropertySlot::Context = PutPropertySlot::UnknownContext);
     static Structure* addPropertyTransitionToExistingStructureConcurrently(Structure*, StringImpl* uid, unsigned attributes, JSCell* specificValue, PropertyOffset&);
     JS_EXPORT_PRIVATE static Structure* addPropertyTransitionToExistingStructure(Structure*, PropertyName, unsigned attributes, JSCell* specificValue, PropertyOffset&);
     static Structure* removePropertyTransition(VM&, Structure*, PropertyName, PropertyOffset&);
@@ -464,6 +465,7 @@ private:
     void cloneRareDataFrom(VM&, const Structure*);
 
     static const int s_maxTransitionLength = 64;
+    static const int s_maxTransitionLengthForNonEvalPutById = 512;
 
     static const unsigned maxSpecificFunctionThrashCount = 3;