Title: [185160] trunk
Revision
185160
Author
[email protected]
Date
2015-06-03 13:04:00 -0700 (Wed, 03 Jun 2015)

Log Message

GetById and PutById profiling should be more precise about it takes slow path
https://bugs.webkit.org/show_bug.cgi?id=145590

Reviewed by Geoffrey Garen.
        
Source/_javascript_Core:

If a ById access ever takes slow path, we want the DFG and FTL to know this. Previously we
were relying on slow path counts, which conflate slow paths taken due to a megamorphic
access and slow paths taken due to IC building.

* bytecode/GetByIdStatus.cpp:
(JSC::GetByIdStatus::computeFor):
(JSC::GetByIdStatus::computeForStubInfo):
* bytecode/PutByIdStatus.cpp:
(JSC::PutByIdStatus::computeFor):
(JSC::PutByIdStatus::computeForStubInfo):
* bytecode/StructureStubInfo.h:
(JSC::StructureStubInfo::StructureStubInfo):
* ftl/FTLIntrinsicRepository.h:
* ftl/FTLLowerDFGToLLVM.cpp:
(JSC::FTL::LowerDFGToLLVM::compileGetById):
* jit/JITOperations.cpp:
* jit/JITOperations.h:

LayoutTests:

Added just two more tests for getters and setters. I needed more microbenchmarks to track
down a regression in an earlier version of this patch.

* js/regress/getter-prototype-expected.txt: Added.
* js/regress/getter-prototype.html: Added.
* js/regress/script-tests/getter-prototype.js: Added.
* js/regress/script-tests/setter-prototype.js: Added.
* js/regress/setter-prototype-expected.txt: Added.
* js/regress/setter-prototype.html: Added.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (185159 => 185160)


--- trunk/LayoutTests/ChangeLog	2015-06-03 19:46:18 UTC (rev 185159)
+++ trunk/LayoutTests/ChangeLog	2015-06-03 20:04:00 UTC (rev 185160)
@@ -1,3 +1,20 @@
+2015-06-02  Filip Pizlo  <[email protected]>
+
+        GetById and PutById profiling should be more precise about it takes slow path
+        https://bugs.webkit.org/show_bug.cgi?id=145590
+
+        Reviewed by Geoffrey Garen.
+        
+        Added just two more tests for getters and setters. I needed more microbenchmarks to track
+        down a regression in an earlier version of this patch.
+
+        * js/regress/getter-prototype-expected.txt: Added.
+        * js/regress/getter-prototype.html: Added.
+        * js/regress/script-tests/getter-prototype.js: Added.
+        * js/regress/script-tests/setter-prototype.js: Added.
+        * js/regress/setter-prototype-expected.txt: Added.
+        * js/regress/setter-prototype.html: Added.
+
 2015-06-03  Zalan Bujtas  <[email protected]>
 
         [iOS] Rebaseline expected results for <br>

Added: trunk/LayoutTests/js/regress/getter-prototype-expected.txt (0 => 185160)


--- trunk/LayoutTests/js/regress/getter-prototype-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/js/regress/getter-prototype-expected.txt	2015-06-03 20:04:00 UTC (rev 185160)
@@ -0,0 +1,10 @@
+JSRegress/getter-prototype
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS no exception thrown
+PASS successfullyParsed is true
+
+TEST COMPLETE
+

Added: trunk/LayoutTests/js/regress/getter-prototype.html (0 => 185160)


--- trunk/LayoutTests/js/regress/getter-prototype.html	                        (rev 0)
+++ trunk/LayoutTests/js/regress/getter-prototype.html	2015-06-03 20:04:00 UTC (rev 185160)
@@ -0,0 +1,12 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<script src=""
+</head>
+<body>
+<script src=""
+<script src=""
+<script src=""
+<script src=""
+</body>
+</html>

Added: trunk/LayoutTests/js/regress/script-tests/getter-prototype.js (0 => 185160)


--- trunk/LayoutTests/js/regress/script-tests/getter-prototype.js	                        (rev 0)
+++ trunk/LayoutTests/js/regress/script-tests/getter-prototype.js	2015-06-03 20:04:00 UTC (rev 185160)
@@ -0,0 +1,21 @@
+function Foo() {
+    this._f = 42;
+}
+
+Foo.prototype.__defineGetter__("f", function() { return this._f; });
+
+function foo(o) {
+    var result = 0;
+    for (var i = 0; i < 1000; ++i)
+        result += o.f;
+    return result;
+}
+
+noInline(foo);
+
+for (var i = 0; i < 10000; ++i) {
+    var result = foo(new Foo());
+    if (result != 1000 * 42)
+        throw "Error: bad result: " + result;
+}
+

Added: trunk/LayoutTests/js/regress/script-tests/setter-prototype.js (0 => 185160)


--- trunk/LayoutTests/js/regress/script-tests/setter-prototype.js	                        (rev 0)
+++ trunk/LayoutTests/js/regress/script-tests/setter-prototype.js	2015-06-03 20:04:00 UTC (rev 185160)
@@ -0,0 +1,21 @@
+function Foo() {
+    this._f = 42;
+}
+
+Foo.prototype.__defineGetter__("f", function() { return this._f; });
+Foo.prototype.__defineSetter__("f", function(value) { this._f = value; });
+
+function foo(o, value) {
+    for (var i = 0; i < 1000; ++i)
+        o.f = value;
+    return o.f;
+}
+
+noInline(foo);
+
+for (var i = 0; i < 10000; ++i) {
+    var result = foo(new Foo(), 42);
+    if (result != 42)
+        throw "Error: bad result: " + result;
+}
+

Added: trunk/LayoutTests/js/regress/setter-prototype-expected.txt (0 => 185160)


--- trunk/LayoutTests/js/regress/setter-prototype-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/js/regress/setter-prototype-expected.txt	2015-06-03 20:04:00 UTC (rev 185160)
@@ -0,0 +1,10 @@
+JSRegress/setter-prototype
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS no exception thrown
+PASS successfullyParsed is true
+
+TEST COMPLETE
+

Added: trunk/LayoutTests/js/regress/setter-prototype.html (0 => 185160)


--- trunk/LayoutTests/js/regress/setter-prototype.html	                        (rev 0)
+++ trunk/LayoutTests/js/regress/setter-prototype.html	2015-06-03 20:04:00 UTC (rev 185160)
@@ -0,0 +1,12 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<script src=""
+</head>
+<body>
+<script src=""
+<script src=""
+<script src=""
+<script src=""
+</body>
+</html>

Modified: trunk/Source/_javascript_Core/ChangeLog (185159 => 185160)


--- trunk/Source/_javascript_Core/ChangeLog	2015-06-03 19:46:18 UTC (rev 185159)
+++ trunk/Source/_javascript_Core/ChangeLog	2015-06-03 20:04:00 UTC (rev 185160)
@@ -1,3 +1,28 @@
+2015-06-02  Filip Pizlo  <[email protected]>
+
+        GetById and PutById profiling should be more precise about it takes slow path
+        https://bugs.webkit.org/show_bug.cgi?id=145590
+
+        Reviewed by Geoffrey Garen.
+        
+        If a ById access ever takes slow path, we want the DFG and FTL to know this. Previously we
+        were relying on slow path counts, which conflate slow paths taken due to a megamorphic
+        access and slow paths taken due to IC building.
+
+        * bytecode/GetByIdStatus.cpp:
+        (JSC::GetByIdStatus::computeFor):
+        (JSC::GetByIdStatus::computeForStubInfo):
+        * bytecode/PutByIdStatus.cpp:
+        (JSC::PutByIdStatus::computeFor):
+        (JSC::PutByIdStatus::computeForStubInfo):
+        * bytecode/StructureStubInfo.h:
+        (JSC::StructureStubInfo::StructureStubInfo):
+        * ftl/FTLIntrinsicRepository.h:
+        * ftl/FTLLowerDFGToLLVM.cpp:
+        (JSC::FTL::LowerDFGToLLVM::compileGetById):
+        * jit/JITOperations.cpp:
+        * jit/JITOperations.h:
+
 2015-06-03  Michael Saboff  <[email protected]>
 
         Improve test coverage for changes made in 145527

Modified: trunk/Source/_javascript_Core/bytecode/GetByIdStatus.cpp (185159 => 185160)


--- trunk/Source/_javascript_Core/bytecode/GetByIdStatus.cpp	2015-06-03 19:46:18 UTC (rev 185159)
+++ trunk/Source/_javascript_Core/bytecode/GetByIdStatus.cpp	2015-06-03 20:04:00 UTC (rev 185160)
@@ -103,8 +103,7 @@
         CallLinkStatus::computeExitSiteData(locker, profiledBlock, bytecodeIndex));
     
     if (!result.takesSlowPath()
-        && (hasExitSite(locker, profiledBlock, bytecodeIndex)
-            || profiledBlock->likelyToTakeSlowCase(bytecodeIndex)))
+        && hasExitSite(locker, profiledBlock, bytecodeIndex))
         return GetByIdStatus(result.makesCalls() ? MakesCalls : TakesSlowPath, true);
 #else
     UNUSED_PARAM(map);
@@ -121,9 +120,12 @@
     const ConcurrentJITLocker& locker, CodeBlock* profiledBlock, StructureStubInfo* stubInfo, UniquedStringImpl* uid,
     CallLinkStatus::ExitSiteData callExitSiteData)
 {
-    if (!stubInfo || !stubInfo->seen)
+    if (!stubInfo)
         return GetByIdStatus(NoInformation);
     
+    if (!stubInfo->seen)
+        return GetByIdStatus(NoInformation);
+    
     PolymorphicGetByIdList* list = 0;
     State slowPathState = TakesSlowPath;
     if (stubInfo->accessType == access_get_by_id_list) {
@@ -135,6 +137,9 @@
         }
     }
     
+    if (stubInfo->tookSlowPath)
+        return GetByIdStatus(slowPathState);
+    
     // Finally figure out if we can derive an access strategy.
     GetByIdStatus result;
     result.m_state = Simple;

Modified: trunk/Source/_javascript_Core/bytecode/PutByIdStatus.cpp (185159 => 185160)


--- trunk/Source/_javascript_Core/bytecode/PutByIdStatus.cpp	2015-06-03 19:46:18 UTC (rev 185159)
+++ trunk/Source/_javascript_Core/bytecode/PutByIdStatus.cpp	2015-06-03 20:04:00 UTC (rev 185160)
@@ -113,8 +113,7 @@
     UNUSED_PARAM(bytecodeIndex);
     UNUSED_PARAM(uid);
 #if ENABLE(DFG_JIT)
-    if (profiledBlock->likelyToTakeSlowCase(bytecodeIndex)
-        || hasExitSite(locker, profiledBlock, bytecodeIndex))
+    if (hasExitSite(locker, profiledBlock, bytecodeIndex))
         return PutByIdStatus(TakesSlowPath);
     
     StructureStubInfo* stubInfo = map.get(CodeOrigin(bytecodeIndex));
@@ -136,9 +135,15 @@
     const ConcurrentJITLocker& locker, CodeBlock* profiledBlock, StructureStubInfo* stubInfo,
     UniquedStringImpl* uid, CallLinkStatus::ExitSiteData callExitSiteData)
 {
-    if (!stubInfo || !stubInfo->seen)
+    if (!stubInfo)
         return PutByIdStatus();
     
+    if (stubInfo->tookSlowPath)
+        return PutByIdStatus(TakesSlowPath);
+    
+    if (!stubInfo->seen)
+        return PutByIdStatus();
+    
     switch (stubInfo->accessType) {
     case access_unset:
         // If the JIT saw it but didn't optimize it, then assume that this takes slow path.

Modified: trunk/Source/_javascript_Core/bytecode/StructureStubInfo.h (185159 => 185160)


--- trunk/Source/_javascript_Core/bytecode/StructureStubInfo.h	2015-06-03 19:46:18 UTC (rev 185159)
+++ trunk/Source/_javascript_Core/bytecode/StructureStubInfo.h	2015-06-03 20:04:00 UTC (rev 185160)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2008, 2012, 2013, 2014 Apple Inc. All rights reserved.
+ * Copyright (C) 2008, 2012-2015 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -94,6 +94,7 @@
         : accessType(access_unset)
         , seen(false)
         , resetByGC(false)
+        , tookSlowPath(false)
     {
     }
 
@@ -183,6 +184,7 @@
     int8_t accessType;
     bool seen : 1;
     bool resetByGC : 1;
+    bool tookSlowPath : 1;
 
     CodeOrigin codeOrigin;
 

Modified: trunk/Source/_javascript_Core/ftl/FTLIntrinsicRepository.h (185159 => 185160)


--- trunk/Source/_javascript_Core/ftl/FTLIntrinsicRepository.h	2015-06-03 19:46:18 UTC (rev 185159)
+++ trunk/Source/_javascript_Core/ftl/FTLIntrinsicRepository.h	2015-06-03 20:04:00 UTC (rev 185160)
@@ -83,6 +83,7 @@
     macro(J_JITOperation_EJ, functionType(int64, intPtr, int64)) \
     macro(J_JITOperation_EJA, functionType(int64, intPtr, int64, intPtr)) \
     macro(J_JITOperation_EJC, functionType(int64, intPtr, int64, intPtr)) \
+    macro(J_JITOperation_EJI, functionType(int64, intPtr, int64, intPtr)) \
     macro(J_JITOperation_EJJ, functionType(int64, intPtr, int64, int64)) \
     macro(J_JITOperation_EJscC, functionType(intPtr, intPtr, intPtr, intPtr)) \
     macro(J_JITOperation_EJssZ, functionType(int64, intPtr, intPtr, int32)) \

Modified: trunk/Source/_javascript_Core/ftl/FTLLowerDFGToLLVM.cpp (185159 => 185160)


--- trunk/Source/_javascript_Core/ftl/FTLLowerDFGToLLVM.cpp	2015-06-03 19:46:18 UTC (rev 185159)
+++ trunk/Source/_javascript_Core/ftl/FTLLowerDFGToLLVM.cpp	2015-06-03 20:04:00 UTC (rev 185160)
@@ -2069,8 +2069,8 @@
             
             m_out.appendTo(notCellCase, continuation);
             ValueFromBlock notCellResult = m_out.anchor(vmCall(
-                m_out.operation(operationGetById),
-                m_callFrame, getUndef(m_out.intPtr), value,
+                m_out.operation(operationGetByIdGeneric),
+                m_callFrame, value,
                 m_out.constIntPtr(m_graph.identifiers()[m_node->identifierNumber()])));
             m_out.jump(continuation);
             

Modified: trunk/Source/_javascript_Core/jit/JITOperations.cpp (185159 => 185160)


--- trunk/Source/_javascript_Core/jit/JITOperations.cpp	2015-06-03 19:46:18 UTC (rev 185159)
+++ trunk/Source/_javascript_Core/jit/JITOperations.cpp	2015-06-03 20:04:00 UTC (rev 185160)
@@ -147,17 +147,30 @@
     return missingArgCount;
 }
 
-EncodedJSValue JIT_OPERATION operationGetById(ExecState* exec, StructureStubInfo*, EncodedJSValue base, UniquedStringImpl* uid)
+EncodedJSValue JIT_OPERATION operationGetById(ExecState* exec, StructureStubInfo* stubInfo, EncodedJSValue base, UniquedStringImpl* uid)
 {
     VM* vm = &exec->vm();
     NativeCallFrameTracer tracer(vm, exec);
     
+    stubInfo->tookSlowPath = true;
+    
     JSValue baseValue = JSValue::decode(base);
     PropertySlot slot(baseValue);
     Identifier ident = Identifier::fromUid(vm, uid);
     return JSValue::encode(baseValue.get(exec, ident, slot));
 }
 
+EncodedJSValue JIT_OPERATION operationGetByIdGeneric(ExecState* exec, EncodedJSValue base, UniquedStringImpl* uid)
+{
+    VM* vm = &exec->vm();
+    NativeCallFrameTracer tracer(vm, exec);
+    
+    JSValue baseValue = JSValue::decode(base);
+    PropertySlot slot(baseValue);
+    Identifier ident = Identifier::fromUid(vm, uid);
+    return JSValue::encode(baseValue.get(exec, ident, slot));
+}
+
 EncodedJSValue JIT_OPERATION operationGetByIdBuildList(ExecState* exec, StructureStubInfo* stubInfo, EncodedJSValue base, UniquedStringImpl* uid)
 {
     VM* vm = &exec->vm();
@@ -221,10 +234,12 @@
     return JSValue::encode(jsBoolean(result));
 }
 
-EncodedJSValue JIT_OPERATION operationIn(ExecState* exec, StructureStubInfo*, JSCell* base, UniquedStringImpl* key)
+EncodedJSValue JIT_OPERATION operationIn(ExecState* exec, StructureStubInfo* stubInfo, JSCell* base, UniquedStringImpl* key)
 {
     VM* vm = &exec->vm();
     NativeCallFrameTracer tracer(vm, exec);
+    
+    stubInfo->tookSlowPath = true;
 
     if (!base->isObject()) {
         vm->throwException(exec, createInvalidInParameterError(exec, base));
@@ -243,41 +258,49 @@
     return JSValue::encode(jsBoolean(CommonSlowPaths::opIn(exec, JSValue::decode(key), base)));
 }
 
-void JIT_OPERATION operationPutByIdStrict(ExecState* exec, StructureStubInfo*, EncodedJSValue encodedValue, EncodedJSValue encodedBase, UniquedStringImpl* uid)
+void JIT_OPERATION operationPutByIdStrict(ExecState* exec, StructureStubInfo* stubInfo, EncodedJSValue encodedValue, EncodedJSValue encodedBase, UniquedStringImpl* uid)
 {
     VM* vm = &exec->vm();
     NativeCallFrameTracer tracer(vm, exec);
     
+    stubInfo->tookSlowPath = true;
+    
     Identifier ident = Identifier::fromUid(vm, uid);
     PutPropertySlot slot(JSValue::decode(encodedBase), true, exec->codeBlock()->putByIdContext());
     JSValue::decode(encodedBase).put(exec, ident, JSValue::decode(encodedValue), slot);
 }
 
-void JIT_OPERATION operationPutByIdNonStrict(ExecState* exec, StructureStubInfo*, EncodedJSValue encodedValue, EncodedJSValue encodedBase, UniquedStringImpl* uid)
+void JIT_OPERATION operationPutByIdNonStrict(ExecState* exec, StructureStubInfo* stubInfo, EncodedJSValue encodedValue, EncodedJSValue encodedBase, UniquedStringImpl* uid)
 {
     VM* vm = &exec->vm();
     NativeCallFrameTracer tracer(vm, exec);
     
+    stubInfo->tookSlowPath = true;
+    
     Identifier ident = Identifier::fromUid(vm, uid);
     PutPropertySlot slot(JSValue::decode(encodedBase), false, exec->codeBlock()->putByIdContext());
     JSValue::decode(encodedBase).put(exec, ident, JSValue::decode(encodedValue), slot);
 }
 
-void JIT_OPERATION operationPutByIdDirectStrict(ExecState* exec, StructureStubInfo*, EncodedJSValue encodedValue, EncodedJSValue encodedBase, UniquedStringImpl* uid)
+void JIT_OPERATION operationPutByIdDirectStrict(ExecState* exec, StructureStubInfo* stubInfo, EncodedJSValue encodedValue, EncodedJSValue encodedBase, UniquedStringImpl* uid)
 {
     VM* vm = &exec->vm();
     NativeCallFrameTracer tracer(vm, exec);
     
+    stubInfo->tookSlowPath = true;
+    
     Identifier ident = Identifier::fromUid(vm, uid);
     PutPropertySlot slot(JSValue::decode(encodedBase), true, exec->codeBlock()->putByIdContext());
     asObject(JSValue::decode(encodedBase))->putDirect(exec->vm(), ident, JSValue::decode(encodedValue), slot);
 }
 
-void JIT_OPERATION operationPutByIdDirectNonStrict(ExecState* exec, StructureStubInfo*, EncodedJSValue encodedValue, EncodedJSValue encodedBase, UniquedStringImpl* uid)
+void JIT_OPERATION operationPutByIdDirectNonStrict(ExecState* exec, StructureStubInfo* stubInfo, EncodedJSValue encodedValue, EncodedJSValue encodedBase, UniquedStringImpl* uid)
 {
     VM* vm = &exec->vm();
     NativeCallFrameTracer tracer(vm, exec);
     
+    stubInfo->tookSlowPath = true;
+    
     Identifier ident = Identifier::fromUid(vm, uid);
     PutPropertySlot slot(JSValue::decode(encodedBase), false, exec->codeBlock()->putByIdContext());
     asObject(JSValue::decode(encodedBase))->putDirect(exec->vm(), ident, JSValue::decode(encodedValue), slot);

Modified: trunk/Source/_javascript_Core/jit/JITOperations.h (185159 => 185160)


--- trunk/Source/_javascript_Core/jit/JITOperations.h	2015-06-03 19:46:18 UTC (rev 185159)
+++ trunk/Source/_javascript_Core/jit/JITOperations.h	2015-06-03 20:04:00 UTC (rev 185160)
@@ -108,6 +108,7 @@
 typedef EncodedJSValue JIT_OPERATION (*J_JITOperation_EJZ)(ExecState*, EncodedJSValue, int32_t);
 typedef EncodedJSValue JIT_OPERATION (*J_JITOperation_EJC)(ExecState*, EncodedJSValue, JSCell*);
 typedef EncodedJSValue JIT_OPERATION (*J_JITOperation_EJA)(ExecState*, EncodedJSValue, JSArray*);
+typedef EncodedJSValue JIT_OPERATION (*J_JITOperation_EJI)(ExecState*, EncodedJSValue, UniquedStringImpl*);
 typedef EncodedJSValue JIT_OPERATION (*J_JITOperation_EJIdc)(ExecState*, EncodedJSValue, const Identifier*);
 typedef EncodedJSValue JIT_OPERATION (*J_JITOperation_EJJ)(ExecState*, EncodedJSValue, EncodedJSValue);
 typedef EncodedJSValue JIT_OPERATION (*J_JITOperation_EJssZ)(ExecState*, JSString*, int32_t);
@@ -235,6 +236,7 @@
 int32_t JIT_OPERATION operationCallArityCheck(ExecState*) WTF_INTERNAL;
 int32_t JIT_OPERATION operationConstructArityCheck(ExecState*) 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;
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to