Skip to content
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

Closed
wants to merge 12 commits into from

Conversation

gdbentley
Copy link
Contributor

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.

@ghost ghost added the CLA Signed label Apr 28, 2016
@ghost
Copy link

ghost commented Apr 28, 2016

This pull request has been imported into Phabricator, and discussion and review of the diff will take place at https://reviews.facebook.net/D57369

@hhvm-bot
Copy link
Contributor

@gdbentley updated the pull request - view changes - changes since last import

1 similar comment
@hhvm-bot
Copy link
Contributor

@gdbentley updated the pull request - view changes - changes since last import

@ghost ghost added the CLA Signed label Aug 29, 2016
@aorenste
Copy link
Contributor

New test failures (4) that were not failing on base rev:

hphp/facebook/test/push-blocking:verify_quick_push_blocking - hphp/test/quick/dict/reflect.php: failed
hphp/facebook/test/push-blocking:verify_quick_push_blocking - hphp/test/quick/keyset/reflect.php: failed
hphp/facebook/test/push-blocking:verify_quick_push_blocking - hphp/test/quick/reflect.php: failed
hphp/facebook/test/push-blocking:verify_quick_push_blocking - hphp/test/quick/vec/reflect.php: failed

@hhvm-bot
Copy link
Contributor

@gdbentley updated the pull request - view changes - changes since last import

@ghost ghost added the CLA Signed label Sep 10, 2016
@aorenste
Copy link
Contributor

Latest version looks like it has some compilation errors:

hphp/runtime/vm/bytecode.cpp:1478:17: error: ‘HPHP::jit::Translator’ has not been declared
     !HPHP::jit::Translator::WriteLease().amOwner();
                 ^

@hhvm-bot
Copy link
Contributor

@gdbentley updated the pull request - view changes - changes since last import

@ghost ghost added the CLA Signed label Sep 14, 2016
Copy link
Contributor

@mxw mxw left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good overall! Mostly nits, with one more major question for you.

I didn't audit the list of annotated functions in this pass. I will, but @Orvid, @paulbiss, @aorenste, can at least one of you take a pass also?

ThrowAllErrorsSetter();
~ThrowAllErrorsSetter();

private:
Copy link
Contributor

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;
Copy link
Contributor

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() &&
Copy link
Contributor

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);
}
Copy link
Contributor

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?

Copy link
Contributor Author

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();
Copy link
Contributor

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
Copy link
Contributor

@mxw mxw Sep 20, 2016

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.

Copy link
Contributor Author

@gdbentley gdbentley Sep 21, 2016

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)};
Copy link
Contributor

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);
Copy link
Contributor

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)));
Copy link
Contributor

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.
Copy link
Contributor

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 :]

@mxw
Copy link
Contributor

mxw commented Sep 20, 2016

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>>
Copy link
Contributor

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)

Copy link
Contributor Author

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.

@hhvm-bot
Copy link
Contributor

@gdbentley updated the pull request - view changes - changes since last import

@ghost ghost added the CLA Signed label Sep 21, 2016
@gdbentley
Copy link
Contributor Author

@mxw Completed rebase number 3.

@hhvm-bot
Copy link
Contributor

@gdbentley updated the pull request - view changes - changes since last import

@ghost ghost added the CLA Signed label Sep 22, 2016
@mxw
Copy link
Contributor

mxw commented Sep 23, 2016

This seems to fail catastrophically on our internal integration tests. I'll look into why today or Monday and report back.

@mxw
Copy link
Contributor

mxw commented Sep 27, 2016

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;
Copy link
Contributor

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?

Copy link
Contributor Author

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;
Copy link
Contributor

@markw65 markw65 Sep 28, 2016

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?

Copy link
Contributor Author

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;
Copy link
Contributor

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...

Copy link
Contributor Author

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;
Copy link
Contributor

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.

Copy link
Contributor Author

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());

Copy link
Contributor

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...

Copy link
Contributor Author

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?

Copy link
Contributor

@markw65 markw65 left a 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...

@hhvm-bot
Copy link
Contributor

@gdbentley updated the pull request - view changes - changes since last import

@mxw
Copy link
Contributor

mxw commented Oct 6, 2016

@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 (VMProtect::Pause foo; above your VMRegAnchor), which I've already added to the internal copy of the diff. Tests seem to be passing just fine, so I'm going to rebase and start them again just to be sure. Unless there's something you want to change, no action is needed on your part—I'll land the diff with that update via our usual internal mechanism.

@gdbentley
Copy link
Contributor Author

@mxw Sounds good. Thanks.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

7 participants