Commit 335a8fc3 authored by mstarzinger's avatar mstarzinger Committed by Commit bot

[turbofan] Introduce conditional builders into AstGraphBuilder.

This re-introduces the long lost concept of conditional builder methods
into the AstGraphBuilder that are allowed to return {nullptr} when a
certain optimization does not apply. This can be used to separate our
optimizations in the graph builder clearly from code required for
correctness.

R=bmeurer@chromium.org
BUG=v8:4513
LOG=n

Review URL: https://codereview.chromium.org/1414723004

Cr-Commit-Position: refs/heads/master@{#31694}
parent 0b293d87
......@@ -3331,12 +3331,7 @@ Node* AstGraphBuilder::BuildVariableLoad(Variable* variable,
case VariableLocation::UNALLOCATED: {
// Global var, const, or let variable.
Handle<Name> name = variable->name();
Handle<Object> constant_value =
jsgraph()->isolate()->factory()->GlobalConstantFor(name);
if (!constant_value.is_null()) {
// Optimize global constants like "undefined", "Infinity", and "NaN".
return jsgraph()->Constant(constant_value);
}
if (Node* node = TryLoadGlobalConstant(name)) return node;
Node* value = BuildGlobalLoad(name, feedback, typeof_mode);
states.AddToNode(value, bailout_id, combine);
return value;
......@@ -3754,42 +3749,13 @@ Node* AstGraphBuilder::BuildStoreExternal(ExternalReference reference,
Node* AstGraphBuilder::BuildToBoolean(Node* input) {
// TODO(bmeurer, mstarzinger): Refactor this into a separate optimization
// method.
switch (input->opcode()) {
case IrOpcode::kNumberConstant: {
NumberMatcher m(input);
return jsgraph_->BooleanConstant(!m.Is(0) && !m.IsNaN());
}
case IrOpcode::kHeapConstant: {
Handle<HeapObject> object = HeapObjectMatcher(input).Value();
return jsgraph_->BooleanConstant(object->BooleanValue());
}
case IrOpcode::kJSEqual:
case IrOpcode::kJSNotEqual:
case IrOpcode::kJSStrictEqual:
case IrOpcode::kJSStrictNotEqual:
case IrOpcode::kJSLessThan:
case IrOpcode::kJSLessThanOrEqual:
case IrOpcode::kJSGreaterThan:
case IrOpcode::kJSGreaterThanOrEqual:
case IrOpcode::kJSUnaryNot:
case IrOpcode::kJSToBoolean:
case IrOpcode::kJSDeleteProperty:
case IrOpcode::kJSHasProperty:
case IrOpcode::kJSInstanceOf:
return input;
default:
break;
}
if (Node* node = TryFastToBoolean(input)) return node;
return NewNode(javascript()->ToBoolean(), input);
}
Node* AstGraphBuilder::BuildToName(Node* input, BailoutId bailout_id) {
// TODO(turbofan): Possible optimization is to NOP on name constants. But the
// same caveat as with BuildToBoolean applies, and it should be factored out
// into a JSOperatorReducer.
if (Node* node = TryFastToName(input)) return node;
Node* name = NewNode(javascript()->ToName(), input);
PrepareFrameState(name, bailout_id);
return name;
......@@ -3933,6 +3899,63 @@ Node* AstGraphBuilder::BuildBinaryOp(Node* left, Node* right, Token::Value op) {
}
Node* AstGraphBuilder::TryLoadGlobalConstant(Handle<Name> name) {
// Optimize global constants like "undefined", "Infinity", and "NaN".
Handle<Object> constant_value = isolate()->factory()->GlobalConstantFor(name);
if (!constant_value.is_null()) return jsgraph()->Constant(constant_value);
return nullptr;
}
Node* AstGraphBuilder::TryFastToBoolean(Node* input) {
switch (input->opcode()) {
case IrOpcode::kNumberConstant: {
NumberMatcher m(input);
return jsgraph_->BooleanConstant(!m.Is(0) && !m.IsNaN());
}
case IrOpcode::kHeapConstant: {
Handle<HeapObject> object = HeapObjectMatcher(input).Value();
return jsgraph_->BooleanConstant(object->BooleanValue());
}
case IrOpcode::kJSEqual:
case IrOpcode::kJSNotEqual:
case IrOpcode::kJSStrictEqual:
case IrOpcode::kJSStrictNotEqual:
case IrOpcode::kJSLessThan:
case IrOpcode::kJSLessThanOrEqual:
case IrOpcode::kJSGreaterThan:
case IrOpcode::kJSGreaterThanOrEqual:
case IrOpcode::kJSUnaryNot:
case IrOpcode::kJSToBoolean:
case IrOpcode::kJSDeleteProperty:
case IrOpcode::kJSHasProperty:
case IrOpcode::kJSInstanceOf:
return input;
default:
break;
}
return nullptr;
}
Node* AstGraphBuilder::TryFastToName(Node* input) {
switch (input->opcode()) {
case IrOpcode::kHeapConstant: {
Handle<HeapObject> object = HeapObjectMatcher(input).Value();
if (object->IsName()) return input;
break;
}
case IrOpcode::kJSToString:
case IrOpcode::kJSToName:
case IrOpcode::kJSTypeOf:
return input;
default:
break;
}
return nullptr;
}
bool AstGraphBuilder::CheckOsrEntry(IterationStatement* stmt) {
if (info()->osr_ast_id() == stmt->OsrEntryId()) {
info()->set_osr_expr_stack_height(std::max(
......
......@@ -354,6 +354,19 @@ class AstGraphBuilder : public AstVisitor {
// stack and build a call node using the given call operator.
Node* ProcessArguments(const Operator* op, int arity);
// ===========================================================================
// The following build methods have the same contract as the above ones, but
// they can also return {NULL} to indicate that no fragment was built. Note
// that these are optimizations, disabling any of them should still produce
// correct graphs.
// Optimization for variable load from global object.
Node* TryLoadGlobalConstant(Handle<Name> name);
// Optimizations for automatic type conversion.
Node* TryFastToBoolean(Node* input);
Node* TryFastToName(Node* input);
// ===========================================================================
// The following visitation methods all recursively visit a subtree of the
// underlying AST and extent the graph. The operand stack is mutated in a way
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment