2016-07-18 09:23:28 +00:00
|
|
|
// Copyright 2016 the V8 project authors. All rights reserved.
|
|
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
|
|
// found in the LICENSE file.
|
|
|
|
|
|
|
|
#ifndef V8_DEOPTIMIZE_REASON_H_
|
|
|
|
#define V8_DEOPTIMIZE_REASON_H_
|
|
|
|
|
|
|
|
#include "src/globals.h"
|
|
|
|
|
|
|
|
namespace v8 {
|
|
|
|
namespace internal {
|
|
|
|
|
2017-08-28 05:26:15 +00:00
|
|
|
#define DEOPTIMIZE_REASON_LIST(V) \
|
2018-12-11 10:22:02 +00:00
|
|
|
V(ArrayBufferWasDetached, "array buffer was detached") \
|
2017-10-12 15:28:53 +00:00
|
|
|
V(CowArrayElementsChanged, "copy-on-write array's elements changed") \
|
2018-01-09 10:58:05 +00:00
|
|
|
V(CouldNotGrowElements, "failed to grow elements store") \
|
|
|
|
V(DeoptimizeNow, "%_DeoptimizeNow") \
|
2017-08-28 05:26:15 +00:00
|
|
|
V(DivisionByZero, "division by zero") \
|
|
|
|
V(Hole, "hole") \
|
|
|
|
V(InstanceMigrationFailed, "instance migration failed") \
|
|
|
|
V(InsufficientTypeFeedbackForCall, "Insufficient type feedback for call") \
|
|
|
|
V(InsufficientTypeFeedbackForConstruct, \
|
|
|
|
"Insufficient type feedback for construct") \
|
|
|
|
V(InsufficientTypeFeedbackForForIn, "Insufficient type feedback for for-in") \
|
2017-09-01 10:29:50 +00:00
|
|
|
V(InsufficientTypeFeedbackForBinaryOperation, \
|
|
|
|
"Insufficient type feedback for binary operation") \
|
|
|
|
V(InsufficientTypeFeedbackForCompareOperation, \
|
|
|
|
"Insufficient type feedback for compare operation") \
|
2017-08-28 05:26:15 +00:00
|
|
|
V(InsufficientTypeFeedbackForGenericNamedAccess, \
|
|
|
|
"Insufficient type feedback for generic named access") \
|
|
|
|
V(InsufficientTypeFeedbackForGenericKeyedAccess, \
|
|
|
|
"Insufficient type feedback for generic keyed access") \
|
2017-11-20 13:36:57 +00:00
|
|
|
V(InsufficientTypeFeedbackForUnaryOperation, \
|
|
|
|
"Insufficient type feedback for unary operation") \
|
2017-08-28 05:26:15 +00:00
|
|
|
V(LostPrecision, "lost precision") \
|
|
|
|
V(LostPrecisionOrNaN, "lost precision or NaN") \
|
|
|
|
V(MinusZero, "minus zero") \
|
|
|
|
V(NaN, "NaN") \
|
|
|
|
V(NoCache, "no cache") \
|
|
|
|
V(NotAHeapNumber, "not a heap number") \
|
|
|
|
V(NotAJavaScriptObject, "not a JavaScript object") \
|
[turbofan] ReceiverOrNullOrUndefined feedback for JSEqual.
This changes the ReceiverOrOddball feedback on JSStrictEqual to
ReceiverOrNullOrUndefined feedback, which can also safely be
consumed by JSEqual (we cannot generally accept any oddball here
since booleans trigger implicit conversions, unfortunately).
Thus we replace the previously introduced CheckReceiverOrOddball
with CheckReceiverOrNullOrUndefined, and drop CheckOddball, since
we will no longer collect Oddball feedback separately.
TurboFan will then turn a JSEqual[ReceiverOrNullOrUndefined] into
a sequence like this:
```
left = CheckReceiverOrNullOrUndefined(left);
right = CheckReceiverOrNullOrUndefined(right);
result = if ObjectIsUndetectable(left) then
ObjectIsUndetectable(right)
else
ReferenceEqual(left, right);
```
This significantly improves the peak performance of abstract equality
with Receiver, Null or Undefined inputs. On the test case outlined in
http://crbug.com/v8/8356 we go from
naive: 2946 ms.
tenary: 2134 ms.
to
naive: 2230 ms.
tenary: 2250 ms.
which corresponds to a 25% improvement on the abstract equality case.
For regular code this will probably yield more performance, since we
get rid of the JSEqual operator, which might have arbitrary side
effects and thus blocks all kinds of TurboFan optimizations. The
JSStrictEqual case is slightly slower now, since it has to rule out
booleans as well (even though that's not strictly necessary, but
consistency is key here).
This way developers can safely use `a == b` instead of doing a dance
like `a == null ? b == null : a === b` (which is what dart2js does
right now) when both `a` and `b` are known to be Receiver, Null or
Undefined. The abstract equality is not only faster to parse than
the tenary, but also generates a shorter bytecode sequence. In the
test case referenced in http://crbug.com/v8/8356 the bytecode for
`naive` is
```
StackCheck
Ldar a1
TestEqual a0, [0]
JumpIfFalse [5]
LdaSmi [1]
Return
LdaSmi [2]
Return
```
which is 14 bytes, whereas the `tenary` function generates
```
StackCheck
Ldar a0
TestUndetectable
JumpIfFalse [7]
Ldar a1
TestUndetectable
Jump [7]
Ldar a1
TestEqualStrict a0, [0]
JumpIfToBooleanFalse [5]
LdaSmi [1]
Return
LdaSmi [2]
Return
```
which is 24 bytes. So the `naive` version is 40% smaller and requires
fewer bytecode dispatches.
Bug: chromium:898455, v8:8356
Change-Id: If3961b2518b4438700706b3bd6071d546305e233
Reviewed-on: https://chromium-review.googlesource.com/c/1297315
Reviewed-by: Jaroslav Sevcik <jarin@chromium.org>
Commit-Queue: Benedikt Meurer <bmeurer@chromium.org>
Cr-Commit-Position: refs/heads/master@{#56948}
2018-10-24 12:09:34 +00:00
|
|
|
V(NotAJavaScriptObjectOrNullOrUndefined, \
|
|
|
|
"not a JavaScript object, Null or Undefined") \
|
2017-08-28 05:26:15 +00:00
|
|
|
V(NotANumberOrOddball, "not a Number or Oddball") \
|
|
|
|
V(NotASmi, "not a Smi") \
|
2018-02-21 14:48:03 +00:00
|
|
|
V(NotAString, "not a String") \
|
2017-08-28 05:26:15 +00:00
|
|
|
V(NotASymbol, "not a Symbol") \
|
|
|
|
V(OutOfBounds, "out of bounds") \
|
|
|
|
V(Overflow, "overflow") \
|
2017-10-12 15:28:53 +00:00
|
|
|
V(ReceiverNotAGlobalProxy, "receiver was not a global proxy") \
|
2017-08-28 05:26:15 +00:00
|
|
|
V(Smi, "Smi") \
|
2018-01-09 10:58:05 +00:00
|
|
|
V(Unknown, "(unknown)") \
|
2017-08-28 05:26:15 +00:00
|
|
|
V(ValueMismatch, "value mismatch") \
|
2018-01-09 10:58:05 +00:00
|
|
|
V(WrongCallTarget, "wrong call target") \
|
|
|
|
V(WrongEnumIndices, "wrong enum indices") \
|
2017-08-28 05:26:15 +00:00
|
|
|
V(WrongInstanceType, "wrong instance type") \
|
[turbofan] Significantly improve ConsString creation performance.
This change significantly improves the performance of string
concatenation in optimized code for the case where the resulting string
is represented as a ConsString. On the relevant test cases we go from
serializeNaive: 10762 ms.
serializeClever: 7813 ms.
serializeConcat: 10271 ms.
to
serializeNaive: 10278 ms.
serializeClever: 5533 ms.
serializeConcat: 10310 ms.
which represents a 30% improvement on the "clever" benchmark, which
tests specifically the ConsString creation performance.
This was accomplished via a couple of different steps, which are briefly
outlined here:
1. The empty_string gets its own map, so that we can easily recognize
and handle it appropriately in the TurboFan type system. This
allows us to express (and assert) that the inputs to NewConsString
are non-empty strings, making sure that TurboFan no longer creates
"crippled ConsStrings" with empty left or right hand sides.
2. Further split the existing String types in TurboFan to be able to
distinguish between OneByte and TwoByte strings on the type system
level. This allows us to avoid having to dynamically lookup the
resulting ConsString map in case of ConsString creation (i.e. when
we know that both input strings are OneByte strings or at least
one of the input strings is TwoByte).
3. We also introduced more finegrained feedback for the Add bytecode
in the interpreter, having it collect feedback about ConsStrings,
specifically ConsOneByteString and ConsTwoByteString. This feedback
can be used by TurboFan to only inline the relevant code for what
was seen so far. This allows us to remove the Octane/Splay specific
magic in JSTypedLowering to detect ConsString creation, and instead
purely rely on the feedback of what was seen so far (also making it
possible to change the semantics of NewConsString to be a low-level
operator, which is only introduced in SimplifiedLowering by looking
at the input types of StringConcat).
4. On top of the before mentioned type and interpreter changes we added
new operators CheckNonEmptyString, CheckNonEmptyOneByteString, and
CheckNonEmptyTwoByteString, which perform the appropriate (dynamic)
checks.
There are several more improvements that are possible based on this, but
since the change was already quite big, we decided not to put everything
into the first change, but do some follow up tweaks to the type system,
and builtin optimizations later.
Tbr: mstarzinger@chromium.org
Bug: v8:8834, v8:8931, v8:8939, v8:8951
Change-Id: Ia24e17c6048bf2b04df966d3cd441f0edda05c93
Cq-Include-Trybots: luci.chromium.try:linux-blink-rel
Doc: https://bit.ly/fast-string-concatenation-in-javascript
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1499497
Commit-Queue: Michael Achenbach <machenbach@chromium.org>
Reviewed-by: Yang Guo <yangguo@chromium.org>
Reviewed-by: Jaroslav Sevcik <jarin@chromium.org>
Reviewed-by: Mythri Alle <mythria@chromium.org>
Reviewed-by: Benedikt Meurer <bmeurer@chromium.org>
Cr-Commit-Position: refs/heads/master@{#60318}
2019-03-18 19:33:46 +00:00
|
|
|
V(WrongLength, "wrong length") \
|
2017-08-28 05:26:15 +00:00
|
|
|
V(WrongMap, "wrong map") \
|
[ic] Ensure that we make progress on KeyedLoadIC polymorphic name.
In the special case of KeyedLoadIC, where the key that is passed in is a
Name that is always the same we only checked for identity in both the
stub and the TurboFan case, which works fine for symbols and internalized
strings, but doesn't really work with non-internalized strings, where
the identity check will fail, the runtime will internalize the string,
and the IC will then see the original internalized string again and not
progress in the feedback lattice. This leads to tricky deoptimization
loops in TurboFan and constantly missing ICs.
This adds fixes the stub to always try to internalize strings first
when the identity check fails and then doing the check again. If the
name is not found in the string table we miss, since in that case the
string cannot match the previously recorded feedback name (which is
always a unique name).
In TurboFan we represent this checks with new CheckEqualsSymbol and
CheckEqualsInternalizedString operators, which validate the previously
recorded feedback, and the CheckEqualsInternalizedString operator does
the attempt to internalize the input.
Bug: v8:6936, v8:6948, v8:6969
Change-Id: I3f3b4a587c67f00f7c4b60d239eb98a9626fe04a
Reviewed-on: https://chromium-review.googlesource.com/730224
Reviewed-by: Toon Verwaest <verwaest@chromium.org>
Reviewed-by: Jaroslav Sevcik <jarin@chromium.org>
Commit-Queue: Benedikt Meurer <bmeurer@chromium.org>
Cr-Commit-Position: refs/heads/master@{#48784}
2017-10-20 11:36:26 +00:00
|
|
|
V(WrongName, "wrong name") \
|
2018-01-22 11:34:05 +00:00
|
|
|
V(WrongValue, "wrong value") \
|
|
|
|
V(NoInitialElement, "no initial element")
|
2016-07-18 09:23:28 +00:00
|
|
|
|
|
|
|
enum class DeoptimizeReason : uint8_t {
|
|
|
|
#define DEOPTIMIZE_REASON(Name, message) k##Name,
|
|
|
|
DEOPTIMIZE_REASON_LIST(DEOPTIMIZE_REASON)
|
|
|
|
#undef DEOPTIMIZE_REASON
|
|
|
|
};
|
|
|
|
|
2019-04-04 08:46:51 +00:00
|
|
|
V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream&, DeoptimizeReason);
|
2016-07-18 09:23:28 +00:00
|
|
|
|
|
|
|
size_t hash_value(DeoptimizeReason reason);
|
|
|
|
|
2019-04-04 08:46:51 +00:00
|
|
|
V8_EXPORT_PRIVATE char const* DeoptimizeReasonToString(DeoptimizeReason reason);
|
2016-07-18 09:23:28 +00:00
|
|
|
|
|
|
|
} // namespace internal
|
|
|
|
} // namespace v8
|
|
|
|
|
|
|
|
#endif // V8_DEOPTIMIZE_REASON_H_
|