New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Call __IsFoldable functions at jit time when possible. #7025
Conversation
This pull request has been imported into Phabricator, and discussion and review of the diff will take place at https://reviews.facebook.net/D57369 |
2288072
to
b4b910d
Compare
@gdbentley updated the pull request - view changes - changes since last import |
1 similar comment
@gdbentley updated the pull request - view changes - changes since last import |
New test failures (4) that were not failing on base rev:
|
@gdbentley updated the pull request - view changes - changes since last import |
Latest version looks like it has some compilation errors:
|
c45f894
to
1d4be4a
Compare
@gdbentley updated the pull request - view changes - changes since last import |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ThrowAllErrorsSetter(); | ||
~ThrowAllErrorsSetter(); | ||
|
||
private: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: Unindent.
@@ -33,6 +33,15 @@ inline bool RequestInjectionData::getJit() const { | |||
return m_jit; | |||
} | |||
|
|||
inline bool RequestInjectionData::getJitFolding() const { | |||
return m_jitFolding; | |||
return true; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Kill this.
@@ -128,8 +128,9 @@ void raise_recoverable_error(const char *fmt, ...) { | |||
static int64_t g_notice_counter = 0; | |||
|
|||
static bool notice_freq_check(ErrorMode mode) { | |||
if (RuntimeOption::NoticeFrequency <= 0 || | |||
g_notice_counter++ % RuntimeOption::NoticeFrequency != 0) { | |||
if (!g_context->getThrowAllErrors() && |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice.
auto size = str->size(); | ||
if (size >= RuntimeOption::MaxSerializedStringSize) { | ||
throw Exception("Size of serialized string (%d) exceeds max", size); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you split this off into a separate PR?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Without this change, hphp/test/quick/string_replace_overflow.php will fail. See the review in phabricator D57369.
@@ -247,11 +247,15 @@ String HHVM_FUNCTION(serialize, const Variant& value) { | |||
case KindOfPersistentString: | |||
case KindOfString: { | |||
StringData *str = value.getStringData(); | |||
auto size = str->size(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(For the PR in question below, auto const
here.)
// ensure that vmpc is valid for later asserts within the invoke | ||
vmpc() = vmfp()->m_func->getEntry(); | ||
SCOPE_EXIT{ vmpc() = savedPC; }; | ||
#endif |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are the vmRegs always clean when we get here? If not, you need a VMRegAnchor; if so, it's probably not so bad to do this even in opt builds, since it's not very expensive.
Also, use if (debug) { ... }
instead of the ifdefs.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I can't use if (debug)
since that would create a new scope and the SCOPE_EXIT would execute at the wrong time.
auto const numNonVariadicArgs = (int32_t)func->numNonVariadicParams(); | ||
PackedArrayInit args(numArgs); | ||
for (auto bcOff = BCSPRelOffset{(int32_t)numArgs - 1}; | ||
bcOff > BCSPRelOffset{(int32_t)(numArgs - numNonDefaultArgs - 1)}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use static_cast
.
SCOPE_EXIT{ vmpc() = savedPC; }; | ||
#endif | ||
SCOPE_EXIT{ RID().setJitFolding(false); }; | ||
RID().setJitFolding(true); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Swap these two lines (for consistency with the above).
return cns(env, makeStaticString(retVal.m_data.pstr)); | ||
} else if (isArrayLikeType(retVal.m_type)) { | ||
return cns(env, make_array_like_tv( | ||
ArrayData::GetScalarArray(retVal.m_data.parr))); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: Something like
auto const arr = ArrayData::getScalarArray(retVal.m_data.parr);
return cns(env, make_array_like_tv(arr));
@@ -33,7 +33,7 @@ function hash_algos(): array<string>; | |||
* | |||
* @param string $algo - Name of selected hashing algorithm | |||
* (i.e. "md5", "sha256", "haval160,4", etc..) | |||
* @param string $filename - File who's contents are to be hashed. | |||
* @param string $filename - File whose contents are to be hashed. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for cleaning these up while you're here :]
Running internal performance tests as well. Sorry that getting this diff in has taken so long—I just now saw that it's been open since April :\ |
@@ -295,7 +295,7 @@ function php_sapi_name(): string; | |||
* displaying the OS PHP was built on. This will only happen if your uname() | |||
* library call either doesn't exist or doesn't work. | |||
*/ | |||
<<__Native>> | |||
<<__Native, __IsFoldable>> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think this can be foldable. php_uname('n')
can change are run time (if the hostname of the machine changes without restarting HHVM)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You're right. I forgot about the machine name; I was only thinking about the OS version.
@gdbentley updated the pull request - view changes - changes since last import |
f198660
to
f74174e
Compare
@mxw Completed rebase number 3. |
@gdbentley updated the pull request - view changes - changes since last import |
This seems to fail catastrophically on our internal integration tests. I'll look into why today or Monday and report back. |
Okay, I'm pretty sure most of the failures were related to our test-infra. I believe those have been fixed, so I'm testing again. |
@@ -91,7 +91,7 @@ function fb_rename_function(string $orig_func_name, | |||
* @param mixed $input - What string to sanitize. | |||
* @return bool - Sanitized string. | |||
*/ | |||
<<__HipHopSpecific, __Native>> | |||
<<__HipHopSpecific, __Native, __IsFoldable>> | |||
function fb_utf8ize(mixed &$input): bool; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't see where you're dealing with reference parameters... won't this just "optimize" it to the bool result, while failing to sanitize $input?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's not possible to pass const input to this function. I've removed the __IsFoldable.
@@ -568,7 +569,7 @@ function str_pad(string $input, | |||
* @return string - Returns the repeated string. | |||
* | |||
*/ | |||
<<__Native>> | |||
<<__IsFoldable, __Native>> | |||
function str_repeat(string $input, int $multiplier): string; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This seems risky - what about str_repeat('x', 2000000000) ? The resulting static string is going to live forever. Maybe there should be a memory limit on the size of the result?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That seems like an application problem to me. Anyway, if your PHP has code like that, wouldn't you prefer to have one copy of the long string rather than allocate it over and over again for each request?
@@ -1676,7 +1677,7 @@ function levenshtein(string $str1, | |||
* @return int - Returns the number of matching chars in both strings. | |||
* | |||
*/ | |||
<<__Native>> | |||
<<__IsFoldable, __Native>> | |||
function similar_text(string $first, | |||
string $second, | |||
mixed &$percent = null): int; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
more reference parameters... I guess this would be ok as long as you check that no parameter is passed for this arg...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If a parameter is passed, it has to be a variable (so that a reference can be taken). If it's a variable, it can't be constant (null or a literal). I've just tested this function on my branch and a two parameter invocation with string literals gets folded while a three parameter invocation does not.
} | ||
} | ||
if (numArgs != func->numNonVariadicParams()) { | ||
if (!topType(env).hasConstVal()) return nullptr; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You should check hasConstVal(TArr), or (since I think the emitter should guarantee that) add an assert that constAsCell(topC(env)) is an array.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added assert.
g_context->invokeFunc(&retVal, func, args.toArray(), nullptr, nullptr, | ||
nullptr, nullptr, ExecutionContext::InvokeNormal, | ||
!func->unit()->useStrictTypes()); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When we start jitting in separate threads (real soon now), this will almost certainly break. It might already break due to some of the guards that have recently been added to try to enforce that...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What specifically is the concern? That the thread doing the jitting will not have a valid g_context? Should I switch back to the (deprecated) invoke() code?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe we can never call builtins with reference parameters, because the params will never be constants - but I think we should be explicit about it; maybe even check in the emitter that foldable functions don't have non-default reference params.
I'm also wondering worried about separate jit threads...
@gdbentley updated the pull request - view changes - changes since last import |
@gdbentley—Okay, sorry for the delay; we went through several iterations of the protection mechanism before it was fully correct. The issue is resolved by a one-liner ( |
@mxw Sounds good. Thanks. |
This change improves WordPress by 2.5% when run in non-repo mode. MediaWiki improves 0.5%.
FCallBuiltin invocations get optimized but not FCall invocations. Those can be handled in a follow-on.