2016-04-18 08:28:33 +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_COMPILER_EFFECT_CONTROL_LINEARIZER_H_
|
|
|
|
#define V8_COMPILER_EFFECT_CONTROL_LINEARIZER_H_
|
|
|
|
|
|
|
|
#include "src/compiler/common-operator.h"
|
2017-01-02 15:50:55 +00:00
|
|
|
#include "src/compiler/graph-assembler.h"
|
2016-04-18 08:28:33 +00:00
|
|
|
#include "src/compiler/node.h"
|
|
|
|
#include "src/compiler/simplified-operator.h"
|
2016-10-17 10:01:42 +00:00
|
|
|
#include "src/globals.h"
|
2016-04-18 08:28:33 +00:00
|
|
|
|
|
|
|
namespace v8 {
|
|
|
|
namespace internal {
|
|
|
|
|
2016-09-27 11:24:07 +00:00
|
|
|
// Forward declarations.
|
|
|
|
class Callable;
|
2016-04-18 08:28:33 +00:00
|
|
|
class Zone;
|
|
|
|
|
|
|
|
namespace compiler {
|
|
|
|
|
|
|
|
class CommonOperatorBuilder;
|
|
|
|
class SimplifiedOperatorBuilder;
|
|
|
|
class MachineOperatorBuilder;
|
|
|
|
class JSGraph;
|
|
|
|
class Graph;
|
|
|
|
class Schedule;
|
2016-11-16 15:06:05 +00:00
|
|
|
class SourcePositionTable;
|
2016-04-18 08:28:33 +00:00
|
|
|
|
2016-10-17 10:01:42 +00:00
|
|
|
class V8_EXPORT_PRIVATE EffectControlLinearizer {
|
2016-04-18 08:28:33 +00:00
|
|
|
public:
|
2016-11-16 15:06:05 +00:00
|
|
|
EffectControlLinearizer(JSGraph* graph, Schedule* schedule, Zone* temp_zone,
|
|
|
|
SourcePositionTable* source_positions);
|
2016-04-18 08:28:33 +00:00
|
|
|
|
|
|
|
void Run();
|
|
|
|
|
|
|
|
private:
|
2016-06-03 11:37:18 +00:00
|
|
|
void ProcessNode(Node* node, Node** frame_state, Node** effect,
|
|
|
|
Node** control);
|
2016-04-18 08:28:33 +00:00
|
|
|
|
2016-06-03 11:37:18 +00:00
|
|
|
bool TryWireInStateEffect(Node* node, Node* frame_state, Node** effect,
|
|
|
|
Node** control);
|
2017-01-02 15:50:55 +00:00
|
|
|
Node* LowerChangeBitToTagged(Node* node);
|
|
|
|
Node* LowerChangeInt31ToTaggedSigned(Node* node);
|
|
|
|
Node* LowerChangeInt32ToTagged(Node* node);
|
|
|
|
Node* LowerChangeUint32ToTagged(Node* node);
|
|
|
|
Node* LowerChangeFloat64ToTagged(Node* node);
|
|
|
|
Node* LowerChangeFloat64ToTaggedPointer(Node* node);
|
|
|
|
Node* LowerChangeTaggedSignedToInt32(Node* node);
|
|
|
|
Node* LowerChangeTaggedToBit(Node* node);
|
|
|
|
Node* LowerChangeTaggedToInt32(Node* node);
|
|
|
|
Node* LowerChangeTaggedToUint32(Node* node);
|
2017-01-31 08:55:56 +00:00
|
|
|
Node* LowerChangeTaggedToTaggedSigned(Node* node);
|
2017-01-02 15:50:55 +00:00
|
|
|
Node* LowerCheckBounds(Node* node, Node* frame_state);
|
|
|
|
Node* LowerCheckInternalizedString(Node* node, Node* frame_state);
|
2017-10-19 13:02:06 +00:00
|
|
|
void LowerCheckMaps(Node* node, Node* frame_state);
|
2017-08-28 07:27:27 +00:00
|
|
|
Node* LowerCompareMaps(Node* node);
|
2017-01-02 15:50:55 +00:00
|
|
|
Node* LowerCheckNumber(Node* node, Node* frame_state);
|
2017-01-18 07:10:51 +00:00
|
|
|
Node* LowerCheckReceiver(Node* node, Node* frame_state);
|
2017-01-02 15:50:55 +00:00
|
|
|
Node* LowerCheckString(Node* node, Node* frame_state);
|
2017-05-24 14:05:05 +00:00
|
|
|
Node* LowerCheckSeqString(Node* node, Node* frame_state);
|
2017-05-22 12:07:40 +00:00
|
|
|
Node* LowerCheckSymbol(Node* node, Node* frame_state);
|
2017-10-19 13:02:06 +00:00
|
|
|
void LowerCheckIf(Node* node, Node* frame_state);
|
2017-01-02 15:50:55 +00:00
|
|
|
Node* LowerCheckedInt32Add(Node* node, Node* frame_state);
|
|
|
|
Node* LowerCheckedInt32Sub(Node* node, Node* frame_state);
|
|
|
|
Node* LowerCheckedInt32Div(Node* node, Node* frame_state);
|
|
|
|
Node* LowerCheckedInt32Mod(Node* node, Node* frame_state);
|
|
|
|
Node* LowerCheckedUint32Div(Node* node, Node* frame_state);
|
|
|
|
Node* LowerCheckedUint32Mod(Node* node, Node* frame_state);
|
|
|
|
Node* LowerCheckedInt32Mul(Node* node, Node* frame_state);
|
|
|
|
Node* LowerCheckedInt32ToTaggedSigned(Node* node, Node* frame_state);
|
|
|
|
Node* LowerCheckedUint32ToInt32(Node* node, Node* frame_state);
|
|
|
|
Node* LowerCheckedUint32ToTaggedSigned(Node* node, Node* frame_state);
|
|
|
|
Node* LowerCheckedFloat64ToInt32(Node* node, Node* frame_state);
|
|
|
|
Node* LowerCheckedTaggedSignedToInt32(Node* node, Node* frame_state);
|
|
|
|
Node* LowerCheckedTaggedToInt32(Node* node, Node* frame_state);
|
|
|
|
Node* LowerCheckedTaggedToFloat64(Node* node, Node* frame_state);
|
|
|
|
Node* LowerCheckedTaggedToTaggedSigned(Node* node, Node* frame_state);
|
|
|
|
Node* LowerCheckedTaggedToTaggedPointer(Node* node, Node* frame_state);
|
|
|
|
Node* LowerChangeTaggedToFloat64(Node* node);
|
2017-11-16 08:52:43 +00:00
|
|
|
void TruncateTaggedPointerToBit(Node* node, GraphAssemblerLabel<1>* done);
|
2017-01-02 15:50:55 +00:00
|
|
|
Node* LowerTruncateTaggedToBit(Node* node);
|
2017-03-07 10:11:16 +00:00
|
|
|
Node* LowerTruncateTaggedPointerToBit(Node* node);
|
2017-01-02 15:50:55 +00:00
|
|
|
Node* LowerTruncateTaggedToFloat64(Node* node);
|
|
|
|
Node* LowerTruncateTaggedToWord32(Node* node);
|
|
|
|
Node* LowerCheckedTruncateTaggedToWord32(Node* node, Node* frame_state);
|
2017-11-10 14:12:54 +00:00
|
|
|
Node* LowerAllocate(Node* node);
|
2017-09-29 09:10:16 +00:00
|
|
|
Node* LowerObjectIsArrayBufferView(Node* node);
|
2017-11-13 12:00:05 +00:00
|
|
|
Node* LowerObjectIsBigInt(Node* node);
|
2017-07-27 13:09:49 +00:00
|
|
|
Node* LowerObjectIsCallable(Node* node);
|
2017-10-13 08:49:00 +00:00
|
|
|
Node* LowerObjectIsConstructor(Node* node);
|
2017-02-18 12:43:37 +00:00
|
|
|
Node* LowerObjectIsDetectableCallable(Node* node);
|
[es2015] Optimize Object.is baseline and interesting cases.
The Object.is builtin provides an entry point to the abstract operation
SameValue, which properly distinguishes -0 and 0, and also identifies
NaNs. Most of the time you don't need these, but rather just regular
strict equality, but when you do, Object.is(o, -0) is the most readable
way to check for minus zero.
This is for example used in Node.js by formatNumber to properly print -0
for negative zero. However since the builtin thus far implemented as C++
builtin and TurboFan didn't know anything about it, Node.js considering
to go with a more performant, less readable version (which also makes
assumptions about the input value) in
https://github.com/nodejs/node/pull/15726
until the performance of Object.is will be on par (so hopefully we can
go back to Object.is in Node 9).
This CL ports the baseline implementation of Object.is to CSA, which
is pretty straight-forward since SameValue is already available in
CodeStubAssembler, and inlines a few interesting cases into TurboFan,
i.e. comparing same SSA node, and checking for -0 and NaN explicitly.
On the micro-benchmarks we go from
testNumberIsMinusZero: 1000 ms.
testObjectIsMinusZero: 929 ms.
testObjectIsNaN: 954 ms.
testObjectIsSame: 793 ms.
testStrictEqualSame: 104 ms.
to
testNumberIsMinusZero: 89 ms.
testObjectIsMinusZero: 88 ms.
testObjectIsNaN: 88 ms.
testObjectIsSame: 86 ms.
testStrictEqualSame: 105 ms.
which is a nice 10x to 11x improvement and brings Object.is on par with
strict equality for most cases.
Drive-by-fix: Also refactor and optimize the SameValue check in the
CodeStubAssembler to avoid code bloat (by not inlining StrictEqual
into every user of SameValue, and also avoiding useless checks).
Bug: v8:6882
Change-Id: Ibffd8c36511f219fcce0d89ed4e1073f5d6c6344
Reviewed-on: https://chromium-review.googlesource.com/700254
Reviewed-by: Jaroslav Sevcik <jarin@chromium.org>
Commit-Queue: Benedikt Meurer <bmeurer@chromium.org>
Cr-Commit-Position: refs/heads/master@{#48275}
2017-10-04 06:25:26 +00:00
|
|
|
Node* LowerObjectIsMinusZero(Node* node);
|
2017-03-03 09:08:14 +00:00
|
|
|
Node* LowerObjectIsNaN(Node* node);
|
2017-01-19 13:16:27 +00:00
|
|
|
Node* LowerObjectIsNonCallable(Node* node);
|
2017-01-02 15:50:55 +00:00
|
|
|
Node* LowerObjectIsNumber(Node* node);
|
|
|
|
Node* LowerObjectIsReceiver(Node* node);
|
|
|
|
Node* LowerObjectIsSmi(Node* node);
|
|
|
|
Node* LowerObjectIsString(Node* node);
|
2017-03-14 16:14:58 +00:00
|
|
|
Node* LowerObjectIsSymbol(Node* node);
|
2017-01-02 15:50:55 +00:00
|
|
|
Node* LowerObjectIsUndetectable(Node* node);
|
2017-02-28 11:16:27 +00:00
|
|
|
Node* LowerArgumentsFrame(Node* node);
|
|
|
|
Node* LowerArgumentsLength(Node* node);
|
2017-10-09 16:49:07 +00:00
|
|
|
Node* LowerNewDoubleElements(Node* node);
|
|
|
|
Node* LowerNewSmiOrObjectElements(Node* node);
|
2017-09-04 11:49:25 +00:00
|
|
|
Node* LowerNewArgumentsElements(Node* node);
|
2017-11-30 03:56:35 +00:00
|
|
|
Node* LowerNewConsString(Node* node);
|
2017-01-02 15:50:55 +00:00
|
|
|
Node* LowerArrayBufferWasNeutered(Node* node);
|
2017-10-27 07:34:03 +00:00
|
|
|
Node* LowerSameValue(Node* node);
|
2017-10-19 09:39:49 +00:00
|
|
|
Node* LowerStringToNumber(Node* node);
|
2017-01-02 15:50:55 +00:00
|
|
|
Node* LowerStringCharAt(Node* node);
|
|
|
|
Node* LowerStringCharCodeAt(Node* node);
|
2017-05-24 11:50:14 +00:00
|
|
|
Node* LowerSeqStringCharCodeAt(Node* node);
|
2017-06-26 08:19:08 +00:00
|
|
|
Node* LowerStringToLowerCaseIntl(Node* node);
|
|
|
|
Node* LowerStringToUpperCaseIntl(Node* node);
|
2017-01-02 15:50:55 +00:00
|
|
|
Node* LowerStringFromCharCode(Node* node);
|
|
|
|
Node* LowerStringFromCodePoint(Node* node);
|
2017-01-27 12:02:42 +00:00
|
|
|
Node* LowerStringIndexOf(Node* node);
|
2017-11-30 06:10:35 +00:00
|
|
|
Node* LowerStringLength(Node* node);
|
2017-01-02 15:50:55 +00:00
|
|
|
Node* LowerStringEqual(Node* node);
|
|
|
|
Node* LowerStringLessThan(Node* node);
|
|
|
|
Node* LowerStringLessThanOrEqual(Node* node);
|
|
|
|
Node* LowerCheckFloat64Hole(Node* node, Node* frame_state);
|
2017-06-06 09:00:22 +00:00
|
|
|
Node* LowerCheckNotTaggedHole(Node* node, Node* frame_state);
|
2017-01-02 15:50:55 +00:00
|
|
|
Node* LowerConvertTaggedHoleToUndefined(Node* node);
|
[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
|
|
|
void LowerCheckEqualsInternalizedString(Node* node, Node* frame_state);
|
|
|
|
void LowerCheckEqualsSymbol(Node* node, Node* frame_state);
|
2017-10-16 09:23:53 +00:00
|
|
|
Node* LowerTypeOf(Node* node);
|
2017-10-19 12:49:32 +00:00
|
|
|
Node* LowerClassOf(Node* node);
|
2017-10-19 08:11:17 +00:00
|
|
|
Node* LowerToBoolean(Node* node);
|
2017-01-02 15:50:55 +00:00
|
|
|
Node* LowerPlainPrimitiveToNumber(Node* node);
|
|
|
|
Node* LowerPlainPrimitiveToWord32(Node* node);
|
|
|
|
Node* LowerPlainPrimitiveToFloat64(Node* node);
|
|
|
|
Node* LowerEnsureWritableFastElements(Node* node);
|
|
|
|
Node* LowerMaybeGrowFastElements(Node* node, Node* frame_state);
|
|
|
|
void LowerTransitionElementsKind(Node* node);
|
2017-09-01 10:49:06 +00:00
|
|
|
Node* LowerLoadFieldByIndex(Node* node);
|
2017-01-02 15:50:55 +00:00
|
|
|
Node* LowerLoadTypedElement(Node* node);
|
|
|
|
void LowerStoreTypedElement(Node* node);
|
2017-10-09 14:03:51 +00:00
|
|
|
void LowerStoreSignedSmallElement(Node* node);
|
2017-10-09 18:41:12 +00:00
|
|
|
Node* LowerFindOrderedHashMapEntry(Node* node);
|
2017-10-25 17:35:15 +00:00
|
|
|
Node* LowerFindOrderedHashMapEntryForInt32Key(Node* node);
|
2017-07-13 08:16:17 +00:00
|
|
|
void LowerTransitionAndStoreElement(Node* node);
|
2017-10-16 08:21:45 +00:00
|
|
|
void LowerTransitionAndStoreNumberElement(Node* node);
|
|
|
|
void LowerTransitionAndStoreNonNumberElement(Node* node);
|
2017-09-08 11:46:07 +00:00
|
|
|
void LowerRuntimeAbort(Node* node);
|
2017-10-26 07:12:38 +00:00
|
|
|
Node* LowerConvertReceiver(Node* node);
|
2016-06-10 07:41:45 +00:00
|
|
|
|
2016-08-05 10:05:49 +00:00
|
|
|
// Lowering of optional operators.
|
2017-01-02 15:50:55 +00:00
|
|
|
Maybe<Node*> LowerFloat64RoundUp(Node* node);
|
|
|
|
Maybe<Node*> LowerFloat64RoundDown(Node* node);
|
|
|
|
Maybe<Node*> LowerFloat64RoundTiesEven(Node* node);
|
|
|
|
Maybe<Node*> LowerFloat64RoundTruncate(Node* node);
|
|
|
|
|
|
|
|
Node* AllocateHeapNumberWithValue(Node* node);
|
|
|
|
Node* BuildCheckedFloat64ToInt32(CheckForMinusZeroMode mode, Node* value,
|
|
|
|
Node* frame_state);
|
|
|
|
Node* BuildCheckedHeapNumberOrOddballToFloat64(CheckTaggedInputMode mode,
|
|
|
|
Node* value,
|
|
|
|
Node* frame_state);
|
|
|
|
Node* BuildFloat64RoundDown(Node* value);
|
2017-10-09 05:29:15 +00:00
|
|
|
Node* ComputeIntegerHash(Node* value);
|
2017-01-02 15:50:55 +00:00
|
|
|
Node* LowerStringComparison(Callable const& callable, Node* node);
|
2017-07-13 08:16:17 +00:00
|
|
|
Node* IsElementsKindGreaterThan(Node* kind, ElementsKind reference_kind);
|
2016-06-10 07:41:45 +00:00
|
|
|
|
2016-04-18 08:28:33 +00:00
|
|
|
Node* ChangeInt32ToSmi(Node* value);
|
2017-10-09 05:29:15 +00:00
|
|
|
Node* ChangeIntPtrToInt32(Node* value);
|
|
|
|
Node* ChangeUint32ToUintPtr(Node* value);
|
2016-04-18 08:28:33 +00:00
|
|
|
Node* ChangeUint32ToSmi(Node* value);
|
2017-10-09 05:29:15 +00:00
|
|
|
Node* ChangeSmiToIntPtr(Node* value);
|
2016-05-02 10:23:02 +00:00
|
|
|
Node* ChangeSmiToInt32(Node* value);
|
|
|
|
Node* ObjectIsSmi(Node* value);
|
2016-04-18 08:28:33 +00:00
|
|
|
|
|
|
|
Node* SmiMaxValueConstant();
|
|
|
|
Node* SmiShiftBitsConstant();
|
2017-07-13 08:16:17 +00:00
|
|
|
void TransitionElementsTo(Node* node, Node* array, ElementsKind from,
|
|
|
|
ElementsKind to);
|
2016-04-18 08:28:33 +00:00
|
|
|
|
2016-06-02 07:59:29 +00:00
|
|
|
Factory* factory() const;
|
|
|
|
Isolate* isolate() const;
|
2016-04-18 08:28:33 +00:00
|
|
|
JSGraph* jsgraph() const { return js_graph_; }
|
|
|
|
Graph* graph() const;
|
|
|
|
Schedule* schedule() const { return schedule_; }
|
|
|
|
Zone* temp_zone() const { return temp_zone_; }
|
|
|
|
CommonOperatorBuilder* common() const;
|
|
|
|
SimplifiedOperatorBuilder* simplified() const;
|
|
|
|
MachineOperatorBuilder* machine() const;
|
|
|
|
|
2017-01-02 15:50:55 +00:00
|
|
|
GraphAssembler* gasm() { return &graph_assembler_; }
|
2016-06-10 07:41:45 +00:00
|
|
|
|
2016-04-18 08:28:33 +00:00
|
|
|
JSGraph* js_graph_;
|
|
|
|
Schedule* schedule_;
|
|
|
|
Zone* temp_zone_;
|
2016-06-20 10:46:12 +00:00
|
|
|
RegionObservability region_observability_ = RegionObservability::kObservable;
|
2016-11-16 15:06:05 +00:00
|
|
|
SourcePositionTable* source_positions_;
|
2017-01-02 15:50:55 +00:00
|
|
|
GraphAssembler graph_assembler_;
|
2017-04-20 14:27:57 +00:00
|
|
|
Node* frame_state_zapper_; // For tracking down compiler::Node::New crashes.
|
2016-04-18 08:28:33 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
} // namespace compiler
|
|
|
|
} // namespace internal
|
|
|
|
} // namespace v8
|
|
|
|
|
|
|
|
#endif // V8_COMPILER_EFFECT_CONTROL_LINEARIZER_H_
|