Skip to content

Commit

Permalink
Version 3.32.1 (based on 9def087)
Browse files Browse the repository at this point in the history
[turbofan] Don't crash when typing load from a Uint8ClampedArray (Chromium issue 446156).

[turbofan] Truncation of Bit/Word8/16 to Word32 is a no-op (Chromium issue 445859).

[x64] Rearrange code for OOB integer loads (Chromium issue 445858).

Fix %NeverOptimizeFunction() intrinsic (Chromium issue 445732).

[turbofan] Fix invalid bounds check with overflowing offset (Chromium issue 445267).

[turbofan] Raise max virtual registers and call parameter limit (issue 3786).

Performance and stability improvements on all platforms.

Cr-Commit-Position: refs/heads/candidates@{#25351}
  • Loading branch information
v8-autoroll committed Jan 7, 2015
1 parent 799ad2f commit 65e6db5
Show file tree
Hide file tree
Showing 31 changed files with 488 additions and 322 deletions.
21 changes: 21 additions & 0 deletions ChangeLog
Original file line number Diff line number Diff line change
@@ -1,3 +1,24 @@
2015-01-07: Version 3.32.1

[turbofan] Don't crash when typing load from a Uint8ClampedArray
(Chromium issue 446156).

[turbofan] Truncation of Bit/Word8/16 to Word32 is a no-op (Chromium
issue 445859).

[x64] Rearrange code for OOB integer loads (Chromium issue 445858).

Fix %NeverOptimizeFunction() intrinsic (Chromium issue 445732).

[turbofan] Fix invalid bounds check with overflowing offset (Chromium
issue 445267).

[turbofan] Raise max virtual registers and call parameter limit (issue
3786).

Performance and stability improvements on all platforms.


2014-12-23: Version 3.31.74

[turbofan] Turn DCHECK for fixed slot index into a CHECK (Chromium issue
Expand Down
2 changes: 1 addition & 1 deletion DEPS
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ deps = {
"v8/testing/gmock":
Var("git_url") + "/external/googlemock.git" + "@" + "29763965ab52f24565299976b936d1265cb6a271", # from svn revision 501
"v8/tools/clang":
Var("git_url") + "/chromium/src/tools/clang.git" + "@" + "90fb65e7a9a5c9d6d9613dfb0e78921c52ca9cfc",
Var("git_url") + "/chromium/src/tools/clang.git" + "@" + "c945be21f6485fa177b43814f910b76cce921653",
}

deps_os = {
Expand Down
8 changes: 8 additions & 0 deletions src/compiler/control-reducer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -403,6 +403,14 @@ class ControlReducerImpl {
if (n <= 1) return dead(); // No non-control inputs.
if (n == 2) return node->InputAt(0); // Only one non-control input.

// Never remove an effect phi from a (potentially non-terminating) loop.
// Otherwise, we might end up eliminating effect nodes, such as calls,
// before the loop.
if (node->opcode() == IrOpcode::kEffectPhi &&
NodeProperties::GetControlInput(node)->opcode() == IrOpcode::kLoop) {
return node;
}

Node* replacement = NULL;
Node::Inputs inputs = node->inputs();
for (InputIter it = inputs.begin(); n > 1; --n, ++it) {
Expand Down
158 changes: 23 additions & 135 deletions src/compiler/js-typed-lowering.cc
Original file line number Diff line number Diff line change
Expand Up @@ -490,124 +490,34 @@ Reduction JSTypedLowering::ReduceJSStrictEqual(Node* node, bool invert) {
}


Reduction JSTypedLowering::ReduceJSToBooleanInput(Node* input) {
if (input->opcode() == IrOpcode::kJSToBoolean) {
// Recursively try to reduce the input first.
Reduction result = ReduceJSToBoolean(input);
if (result.Changed()) return result;
return Changed(input); // JSToBoolean(JSToBoolean(x)) => JSToBoolean(x)
}
// Check if we have a cached conversion.
Node* conversion = FindConversion<IrOpcode::kJSToBoolean>(input);
if (conversion) return Replace(conversion);
Reduction JSTypedLowering::ReduceJSUnaryNot(Node* node) {
Node* input = node->InputAt(0);
Type* input_type = NodeProperties::GetBounds(input).upper;
if (input_type->Is(Type::Boolean())) {
return Changed(input); // JSToBoolean(x:boolean) => x
}
if (input_type->Is(Type::Undefined())) {
// JSToBoolean(undefined) => #false
return Replace(jsgraph()->FalseConstant());
}
if (input_type->Is(Type::Null())) {
// JSToBoolean(null) => #false
return Replace(jsgraph()->FalseConstant());
}
if (input_type->Is(Type::DetectableReceiver())) {
// JSToBoolean(x:detectable) => #true
return Replace(jsgraph()->TrueConstant());
}
if (input_type->Is(Type::Undetectable())) {
// JSToBoolean(x:undetectable) => #false
return Replace(jsgraph()->FalseConstant());
}
if (input_type->Is(Type::OrderedNumber())) {
// JSToBoolean(x:ordered-number) => BooleanNot(NumberEqual(x, #0))
Node* cmp = graph()->NewNode(simplified()->NumberEqual(), input,
jsgraph()->ZeroConstant());
Node* inv = graph()->NewNode(simplified()->BooleanNot(), cmp);
return Replace(inv);
}
if (input_type->Is(Type::String())) {
// JSToBoolean(x:string) => BooleanNot(NumberEqual(x.length, #0))
FieldAccess access = AccessBuilder::ForStringLength();
Node* length = graph()->NewNode(simplified()->LoadField(access), input,
graph()->start(), graph()->start());
Node* cmp = graph()->NewNode(simplified()->NumberEqual(), length,
jsgraph()->ZeroConstant());
Node* inv = graph()->NewNode(simplified()->BooleanNot(), cmp);
return Replace(inv);
// JSUnaryNot(x:boolean,context) => BooleanNot(x)
node->set_op(simplified()->BooleanNot());
node->TrimInputCount(1);
return Changed(node);
}
return NoChange();
// JSUnaryNot(x,context) => BooleanNot(AnyToBoolean(x))
node->set_op(simplified()->BooleanNot());
node->ReplaceInput(0, graph()->NewNode(simplified()->AnyToBoolean(), input));
node->TrimInputCount(1);
return Changed(node);
}


Reduction JSTypedLowering::ReduceJSToBoolean(Node* node) {
// Try to reduce the input first.
Node* const input = node->InputAt(0);
Reduction reduction = ReduceJSToBooleanInput(input);
if (reduction.Changed()) return reduction;
if (input->opcode() == IrOpcode::kPhi) {
// JSToBoolean(phi(x1,...,xn,control),context)
// => phi(JSToBoolean(x1,no-context),...,JSToBoolean(xn,no-context))
int const input_count = input->InputCount() - 1;
Node* const control = input->InputAt(input_count);
DCHECK_LE(0, input_count);
DCHECK(NodeProperties::IsControl(control));
DCHECK(NodeProperties::GetBounds(node).upper->Is(Type::Boolean()));
DCHECK(!NodeProperties::GetBounds(input).upper->Is(Type::Boolean()));
node->set_op(common()->Phi(kMachAnyTagged, input_count));
for (int i = 0; i < input_count; ++i) {
// We must be very careful not to introduce cycles when pushing
// operations into phis. It is safe for {value}, since it appears
// as input to the phi that we are replacing, but it's not safe
// to simply reuse the context of the {node}. However, ToBoolean()
// does not require a context anyways, so it's safe to discard it
// here and pass the dummy context.
Node* const value = ConvertToBoolean(input->InputAt(i));
if (i < node->InputCount()) {
node->ReplaceInput(i, value);
} else {
node->AppendInput(graph()->zone(), value);
}
}
if (input_count < node->InputCount()) {
node->ReplaceInput(input_count, control);
} else {
node->AppendInput(graph()->zone(), control);
}
node->TrimInputCount(input_count + 1);
return Changed(node);
}
if (input->opcode() == IrOpcode::kSelect) {
// JSToBoolean(select(c,x1,x2),context)
// => select(c,JSToBoolean(x1,no-context),...,JSToBoolean(x2,no-context))
int const input_count = input->InputCount();
BranchHint const input_hint = SelectParametersOf(input->op()).hint();
DCHECK_EQ(3, input_count);
DCHECK(NodeProperties::GetBounds(node).upper->Is(Type::Boolean()));
DCHECK(!NodeProperties::GetBounds(input).upper->Is(Type::Boolean()));
node->set_op(common()->Select(kMachAnyTagged, input_hint));
node->InsertInput(graph()->zone(), 0, input->InputAt(0));
for (int i = 1; i < input_count; ++i) {
// We must be very careful not to introduce cycles when pushing
// operations into selects. It is safe for {value}, since it appears
// as input to the select that we are replacing, but it's not safe
// to simply reuse the context of the {node}. However, ToBoolean()
// does not require a context anyways, so it's safe to discard it
// here and pass the dummy context.
Node* const value = ConvertToBoolean(input->InputAt(i));
node->ReplaceInput(i, value);
}
DCHECK_EQ(3, node->InputCount());
return Changed(node);
}
InsertConversion(node);
if (node->InputAt(1) != jsgraph()->NoContextConstant()) {
// JSToBoolean(x,context) => JSToBoolean(x,no-context)
node->ReplaceInput(1, jsgraph()->NoContextConstant());
return Changed(node);
Node* input = node->InputAt(0);
Type* input_type = NodeProperties::GetBounds(input).upper;
if (input_type->Is(Type::Boolean())) {
// JSToBoolean(x:boolean,context) => x
return Replace(input);
}
return NoChange();
// JSToBoolean(x,context) => AnyToBoolean(x)
node->set_op(simplified()->AnyToBoolean());
node->TrimInputCount(1);
return Changed(node);
}


Expand Down Expand Up @@ -972,18 +882,8 @@ Reduction JSTypedLowering::Reduce(Node* node) {
return ReduceNumberBinop(node, simplified()->NumberDivide());
case IrOpcode::kJSModulus:
return ReduceNumberBinop(node, simplified()->NumberModulus());
case IrOpcode::kJSUnaryNot: {
Reduction result = ReduceJSToBooleanInput(node->InputAt(0));
if (result.Changed()) {
// JSUnaryNot(x:boolean) => BooleanNot(x)
node = result.replacement();
} else {
// JSUnaryNot(x) => BooleanNot(JSToBoolean(x))
node->set_op(javascript()->ToBoolean());
}
Node* value = graph()->NewNode(simplified()->BooleanNot(), node);
return Replace(value);
}
case IrOpcode::kJSUnaryNot:
return ReduceJSUnaryNot(node);
case IrOpcode::kJSToBoolean:
return ReduceJSToBoolean(node);
case IrOpcode::kJSToNumber:
Expand All @@ -1005,17 +905,6 @@ Reduction JSTypedLowering::Reduce(Node* node) {
}


Node* JSTypedLowering::ConvertToBoolean(Node* input) {
// Avoid inserting too many eager ToBoolean() operations.
Reduction const reduction = ReduceJSToBooleanInput(input);
if (reduction.Changed()) return reduction.replacement();
Node* const conversion = graph()->NewNode(javascript()->ToBoolean(), input,
jsgraph()->NoContextConstant());
InsertConversion(conversion);
return conversion;
}


Node* JSTypedLowering::ConvertToNumber(Node* input) {
DCHECK(NodeProperties::GetBounds(input).upper->Is(Type::PlainPrimitive()));
// Avoid inserting too many eager ToNumber() operations.
Expand Down Expand Up @@ -1043,8 +932,7 @@ Node* JSTypedLowering::FindConversion(Node* input) {


void JSTypedLowering::InsertConversion(Node* conversion) {
DCHECK(conversion->opcode() == IrOpcode::kJSToBoolean ||
conversion->opcode() == IrOpcode::kJSToNumber);
DCHECK(conversion->opcode() == IrOpcode::kJSToNumber);
size_t const input_id = conversion->InputAt(0)->id();
if (input_id >= conversions_.size()) {
conversions_.resize(2 * input_id + 1);
Expand Down
3 changes: 1 addition & 2 deletions src/compiler/js-typed-lowering.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ class JSTypedLowering FINAL : public Reducer {
Reduction ReduceJSStoreContext(Node* node);
Reduction ReduceJSEqual(Node* node, bool invert);
Reduction ReduceJSStrictEqual(Node* node, bool invert);
Reduction ReduceJSToBooleanInput(Node* input);
Reduction ReduceJSUnaryNot(Node* node);
Reduction ReduceJSToBoolean(Node* node);
Reduction ReduceJSToNumberInput(Node* input);
Reduction ReduceJSToNumber(Node* node);
Expand All @@ -52,7 +52,6 @@ class JSTypedLowering FINAL : public Reducer {
Reduction ReduceUI32Shift(Node* node, Signedness left_signedness,
const Operator* shift_op);

Node* ConvertToBoolean(Node* input);
Node* ConvertToNumber(Node* input);
template <IrOpcode::Value>
Node* FindConversion(Node* input);
Expand Down
1 change: 1 addition & 0 deletions src/compiler/opcodes.h
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@

// Opcodes for VirtuaMachine-level operators.
#define SIMPLIFIED_OP_LIST(V) \
V(AnyToBoolean) \
V(BooleanNot) \
V(BooleanToNumber) \
V(NumberEqual) \
Expand Down
2 changes: 1 addition & 1 deletion src/compiler/pipeline.cc
Original file line number Diff line number Diff line change
Expand Up @@ -441,7 +441,7 @@ struct SimplifiedLoweringPhase {
void Run(PipelineData* data, Zone* temp_zone) {
SourcePositionTable::Scope pos(data->source_positions(),
SourcePosition::Unknown());
SimplifiedLowering lowering(data->jsgraph());
SimplifiedLowering lowering(data->jsgraph(), temp_zone);
lowering.LowerAllNodes();
ValueNumberingReducer vn_reducer(temp_zone);
SimplifiedOperatorReducer simple_reducer(data->jsgraph());
Expand Down
35 changes: 33 additions & 2 deletions src/compiler/simplified-lowering.cc
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,9 @@ class RepresentationSelector {
memset(info_, 0, sizeof(NodeInfo) * count_);

Factory* f = zone->isolate()->factory();
safe_bit_range_ =
Type::Union(Type::Boolean(),
Type::Range(f->NewNumber(0), f->NewNumber(1), zone), zone);
safe_int_additive_range_ =
Type::Range(f->NewNumber(-std::pow(2.0, 52.0)),
f->NewNumber(std::pow(2.0, 52.0)), zone);
Expand Down Expand Up @@ -320,7 +323,7 @@ class RepresentationSelector {
} else {
return kRepFloat64;
}
} else if (upper->Is(Type::Boolean())) {
} else if (IsSafeBitOperand(node)) {
// multiple uses => pick kRepBit.
return kRepBit;
} else if (upper->Is(Type::Number())) {
Expand Down Expand Up @@ -414,6 +417,11 @@ class RepresentationSelector {
return BothInputsAre(node, Type::Signed32()) && !CanObserveNonInt32(use);
}

bool IsSafeBitOperand(Node* node) {
Type* type = NodeProperties::GetBounds(node).upper;
return type->Is(safe_bit_range_);
}

bool IsSafeIntAdditiveOperand(Node* node) {
Type* type = NodeProperties::GetBounds(node).upper;
// TODO(jarin): Unfortunately, bitset types are not subtypes of larger
Expand Down Expand Up @@ -521,6 +529,28 @@ class RepresentationSelector {
//------------------------------------------------------------------
// Simplified operators.
//------------------------------------------------------------------
case IrOpcode::kAnyToBoolean: {
if (IsSafeBitOperand(node->InputAt(0))) {
VisitUnop(node, kRepBit, kRepBit);
if (lower()) DeferReplacement(node, node->InputAt(0));
} else {
VisitUnop(node, kMachAnyTagged, kTypeBool | kRepTagged);
if (lower()) {
// AnyToBoolean(x) => Call(ToBooleanStub, x, no-context)
Operator::Properties properties = node->op()->properties();
Callable callable = CodeFactory::ToBoolean(
jsgraph_->isolate(), ToBooleanStub::RESULT_AS_ODDBALL);
CallDescriptor::Flags flags = CallDescriptor::kPatchableCallSite;
CallDescriptor* desc = Linkage::GetStubCallDescriptor(
callable.descriptor(), 0, flags, properties, jsgraph_->zone());
node->set_op(jsgraph_->common()->Call(desc));
node->InsertInput(jsgraph_->zone(), 0,
jsgraph_->HeapConstant(callable.code()));
node->AppendInput(jsgraph_->zone(), jsgraph_->NoContextConstant());
}
}
break;
}
case IrOpcode::kBooleanNot: {
if (lower()) {
MachineTypeUnion input = GetInfo(node->InputAt(0))->output;
Expand Down Expand Up @@ -1034,6 +1064,7 @@ class RepresentationSelector {
Phase phase_; // current phase of algorithm
RepresentationChanger* changer_; // for inserting representation changes
ZoneQueue<Node*> queue_; // queue for traversing the graph
Type* safe_bit_range_;
Type* safe_int_additive_range_;

NodeInfo* GetInfo(Node* node) {
Expand All @@ -1058,7 +1089,7 @@ void SimplifiedLowering::LowerAllNodes() {
SimplifiedOperatorBuilder simplified(graph()->zone());
RepresentationChanger changer(jsgraph(), &simplified,
graph()->zone()->isolate());
RepresentationSelector selector(jsgraph(), zone(), &changer);
RepresentationSelector selector(jsgraph(), zone_, &changer);
selector.Run(this);
}

Expand Down
6 changes: 4 additions & 2 deletions src/compiler/simplified-lowering.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ class RepresentationChanger;

class SimplifiedLowering FINAL {
public:
explicit SimplifiedLowering(JSGraph* jsgraph) : jsgraph_(jsgraph) {}
SimplifiedLowering(JSGraph* jsgraph, Zone* zone)
: jsgraph_(jsgraph), zone_(zone) {}
~SimplifiedLowering() {}

void LowerAllNodes();
Expand All @@ -41,7 +42,8 @@ class SimplifiedLowering FINAL {
void DoStringLessThanOrEqual(Node* node);

private:
JSGraph* jsgraph_;
JSGraph* const jsgraph_;
Zone* const zone_;

Node* SmiTag(Node* node);
Node* IsTagged(Node* node);
Expand Down
Loading

0 comments on commit 65e6db5

Please sign in to comment.