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;