Commit 3ec1d591 authored by Jakob Gruber's avatar Jakob Gruber Committed by Commit Bot

[gasm] Strengthen typing

This is an initial (and partial) step towards full typing in graph
assembler. It removes all uses of SloppyTNode, starts to introduce
types in the GraphAssembler base class, and makes lambda function
types (for if- and for-builders) more specific.

Plenty of TODOs remain; e.g. checked casts and complete typing of
GraphAssembler are left to follow-up work.

Bug: v8:9972
Change-Id: I780adf83b53ad76beda4726960d95ab6df13e2ce
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1940476
Commit-Queue: Jakob Gruber <jgruber@chromium.org>
Reviewed-by: 's avatarClemens Backes <clemensb@chromium.org>
Reviewed-by: 's avatarTobias Tebbi <tebbi@chromium.org>
Cr-Commit-Position: refs/heads/master@{#65241}
parent 9ac62c4d
......@@ -81,6 +81,12 @@ struct is_same<T> : public std::true_type {};
template <typename T, typename... Ts>
struct is_same<T, T, Ts...> : public is_same<T, Ts...> {};
// Returns true, iff all values (implicitly converted to bool) are trueish.
template <typename... Args>
constexpr bool all(Args... rest) {
return fold(std::logical_and<>{}, true, rest...);
}
} // namespace base
} // namespace v8
......
......@@ -7,6 +7,11 @@
#include "src/codegen/code-factory.h"
#include "src/compiler/linkage.h"
#include "src/compiler/schedule.h"
// For TNode types.
#include "src/objects/heap-number.h"
#include "src/objects/oddball.h"
#include "src/objects/smi.h"
#include "src/objects/string.h"
namespace v8 {
namespace internal {
......@@ -376,8 +381,9 @@ Node* GraphAssembler::HeapConstant(Handle<HeapObject> object) {
return AddClonedNode(jsgraph()->HeapConstant(object));
}
Node* GraphAssembler::NumberConstant(double value) {
return AddClonedNode(jsgraph()->Constant(value));
TNode<Number> GraphAssembler::NumberConstant(double value) {
return TNode<Number>::UncheckedCast(
AddClonedNode(jsgraph()->Constant(value)));
}
Node* GraphAssembler::ExternalConstant(ExternalReference ref) {
......@@ -392,16 +398,18 @@ Node* GraphAssembler::LoadFramePointer() {
return AddNode(graph()->NewNode(machine()->LoadFramePointer()));
}
#define SINGLETON_CONST_DEF(Name) \
Node* GraphAssembler::Name##Constant() { \
return AddClonedNode(jsgraph()->Name##Constant()); \
#define SINGLETON_CONST_DEF(Name) \
TNode<Object> GraphAssembler::Name##Constant() { \
return TNode<Object>::UncheckedCast( \
AddClonedNode(jsgraph()->Name##Constant())); \
}
JSGRAPH_SINGLETON_CONSTANT_LIST(SINGLETON_CONST_DEF)
#undef SINGLETON_CONST_DEF
#define SINGLETON_CONST_TEST_DEF(Name) \
Node* GraphAssembler::Is##Name(Node* value) { \
return ReferenceEqual(value, Name##Constant()); \
#define SINGLETON_CONST_TEST_DEF(Name) \
TNode<Boolean> GraphAssembler::Is##Name(TNode<Object> value) { \
return TNode<Boolean>::UncheckedCast( \
ReferenceEqual(value, Name##Constant())); \
}
JSGRAPH_SINGLETON_CONSTANT_LIST(SINGLETON_CONST_TEST_DEF)
#undef SINGLETON_CONST_TEST_DEF
......@@ -503,46 +511,54 @@ Node* GraphAssembler::StoreElement(ElementAccess const& access, Node* object,
index, value, effect(), control()));
}
Node* GraphAssembler::StringLength(Node* string) {
return AddNode(graph()->NewNode(simplified()->StringLength(), string));
TNode<Number> GraphAssembler::StringLength(TNode<String> string) {
return AddNode<Number>(
graph()->NewNode(simplified()->StringLength(), string));
}
Node* GraphAssembler::ReferenceEqual(Node* lhs, Node* rhs) {
return AddNode(graph()->NewNode(simplified()->ReferenceEqual(), lhs, rhs));
}
Node* GraphAssembler::NumberMin(Node* lhs, Node* rhs) {
return AddNode(graph()->NewNode(simplified()->NumberMin(), lhs, rhs));
TNode<Number> GraphAssembler::NumberMin(TNode<Number> lhs, TNode<Number> rhs) {
return AddNode<Number>(graph()->NewNode(simplified()->NumberMin(), lhs, rhs));
}
Node* GraphAssembler::NumberMax(Node* lhs, Node* rhs) {
return AddNode(graph()->NewNode(simplified()->NumberMax(), lhs, rhs));
TNode<Number> GraphAssembler::NumberMax(TNode<Number> lhs, TNode<Number> rhs) {
return AddNode<Number>(graph()->NewNode(simplified()->NumberMax(), lhs, rhs));
}
Node* GraphAssembler::NumberAdd(Node* lhs, Node* rhs) {
return AddNode(graph()->NewNode(simplified()->NumberAdd(), lhs, rhs));
TNode<Number> GraphAssembler::NumberAdd(TNode<Number> lhs, TNode<Number> rhs) {
return AddNode<Number>(graph()->NewNode(simplified()->NumberAdd(), lhs, rhs));
}
Node* GraphAssembler::NumberSubtract(Node* lhs, Node* rhs) {
return AddNode(graph()->NewNode(simplified()->NumberSubtract(), lhs, rhs));
TNode<Number> GraphAssembler::NumberSubtract(TNode<Number> lhs,
TNode<Number> rhs) {
return AddNode<Number>(
graph()->NewNode(simplified()->NumberSubtract(), lhs, rhs));
}
Node* GraphAssembler::NumberLessThan(Node* lhs, Node* rhs) {
return AddNode(graph()->NewNode(simplified()->NumberLessThan(), lhs, rhs));
TNode<Boolean> GraphAssembler::NumberLessThan(TNode<Number> lhs,
TNode<Number> rhs) {
return AddNode<Boolean>(
graph()->NewNode(simplified()->NumberLessThan(), lhs, rhs));
}
Node* GraphAssembler::NumberLessThanOrEqual(Node* lhs, Node* rhs) {
return AddNode(
TNode<Boolean> GraphAssembler::NumberLessThanOrEqual(TNode<Number> lhs,
TNode<Number> rhs) {
return AddNode<Boolean>(
graph()->NewNode(simplified()->NumberLessThanOrEqual(), lhs, rhs));
}
Node* GraphAssembler::StringSubstring(Node* string, Node* from, Node* to) {
return AddNode(graph()->NewNode(simplified()->StringSubstring(), string, from,
to, effect(), control()));
TNode<String> GraphAssembler::StringSubstring(Node* string, Node* from,
Node* to) {
return AddNode<String>(graph()->NewNode(
simplified()->StringSubstring(), string, from, to, effect(), control()));
}
Node* GraphAssembler::ObjectIsCallable(Node* value) {
return AddNode(graph()->NewNode(simplified()->ObjectIsCallable(), value));
TNode<Boolean> GraphAssembler::ObjectIsCallable(Node* value) {
return AddNode<Boolean>(
graph()->NewNode(simplified()->ObjectIsCallable(), value));
}
Node* GraphAssembler::CheckIf(Node* cond, DeoptimizeReason reason) {
......
......@@ -5,6 +5,7 @@
#ifndef V8_COMPILER_GRAPH_ASSEMBLER_H_
#define V8_COMPILER_GRAPH_ASSEMBLER_H_
#include "src/codegen/tnode.h"
#include "src/compiler/feedback-source.h"
#include "src/compiler/js-graph.h"
#include "src/compiler/node.h"
......@@ -15,6 +16,12 @@ namespace internal {
class JSGraph;
class Graph;
class Oddball;
// TODO(jgruber): Currently this is too permissive, but at least it lets us
// document which functions expect JS booleans. If a real Boolean type becomes
// possible in the future, use that instead.
using Boolean = Oddball;
namespace compiler {
......@@ -212,17 +219,18 @@ class V8_EXPORT_PRIVATE GraphAssembler {
Node* Float64Constant(double value);
Node* Projection(int index, Node* value);
Node* HeapConstant(Handle<HeapObject> object);
Node* NumberConstant(double value);
TNode<Number> NumberConstant(double value);
Node* CEntryStubConstant(int result_size);
Node* ExternalConstant(ExternalReference ref);
Node* LoadFramePointer();
#define SINGLETON_CONST_DECL(Name) Node* Name##Constant();
#define SINGLETON_CONST_DECL(Name) TNode<Object> Name##Constant();
JSGRAPH_SINGLETON_CONSTANT_LIST(SINGLETON_CONST_DECL)
#undef SINGLETON_CONST_DECL
#define SINGLETON_CONST_TEST_DECL(Name) Node* Is##Name(Node* value);
#define SINGLETON_CONST_TEST_DECL(Name) \
TNode<Boolean> Is##Name(TNode<Object> value);
JSGRAPH_SINGLETON_CONSTANT_LIST(SINGLETON_CONST_TEST_DECL)
#undef SINGLETON_CONST_TEST_DECL
......@@ -259,16 +267,16 @@ class V8_EXPORT_PRIVATE GraphAssembler {
Node* StoreField(FieldAccess const&, Node* object, Node* value);
Node* StoreElement(ElementAccess const&, Node* object, Node* index,
Node* value);
Node* StringLength(Node* string);
TNode<Number> StringLength(TNode<String> string);
Node* ReferenceEqual(Node* lhs, Node* rhs);
Node* NumberMin(Node* lhs, Node* rhs);
Node* NumberMax(Node* lhs, Node* rhs);
Node* NumberLessThan(Node* lhs, Node* rhs);
Node* NumberLessThanOrEqual(Node* lhs, Node* rhs);
Node* NumberAdd(Node* lhs, Node* rhs);
Node* NumberSubtract(Node* lhs, Node* rhs);
Node* StringSubstring(Node* string, Node* from, Node* to);
Node* ObjectIsCallable(Node* value);
TNode<Number> NumberMin(TNode<Number> lhs, TNode<Number> rhs);
TNode<Number> NumberMax(TNode<Number> lhs, TNode<Number> rhs);
TNode<Boolean> NumberLessThan(TNode<Number> lhs, TNode<Number> rhs);
TNode<Boolean> NumberLessThanOrEqual(TNode<Number> lhs, TNode<Number> rhs);
TNode<Number> NumberAdd(TNode<Number> lhs, TNode<Number> rhs);
TNode<Number> NumberSubtract(TNode<Number> lhs, TNode<Number> rhs);
TNode<String> StringSubstring(Node* string, Node* from, Node* to);
TNode<Boolean> ObjectIsCallable(Node* value);
Node* CheckIf(Node* cond, DeoptimizeReason reason);
Node* NumberIsFloat64Hole(Node* value);
......@@ -350,6 +358,11 @@ class V8_EXPORT_PRIVATE GraphAssembler {
// and control.
Node* AddNode(Node* node);
template <typename T>
TNode<T> AddNode(Node* node) {
return TNode<T>::UncheckedCast(AddNode(node));
}
// Finalizes the {block} being processed by the assembler, returning the
// finalized block (which may be different from the original block).
BasicBlock* FinalizeCurrentBlock(BasicBlock* block);
......
......@@ -64,9 +64,14 @@ class V8_EXPORT_PRIVATE Graph final : public NON_EXPORTED_BASE(ZoneObject) {
bool incomplete = false);
// Factory template for nodes with static input counts.
template <typename... Nodes>
Node* NewNode(const Operator* op, Nodes*... nodes) {
std::array<Node*, sizeof...(nodes)> nodes_arr{{nodes...}};
// Note: Template magic below is used to ensure this method is only considered
// for argument types convertible to Node* during overload resoluation.
template <typename... Nodes,
typename = typename std::enable_if_t<
base::all(std::is_convertible<Nodes, Node*>::value...)>>
Node* NewNode(const Operator* op, Nodes... nodes) {
std::array<Node*, sizeof...(nodes)> nodes_arr{
{static_cast<Node*>(nodes)...}};
return NewNode(op, nodes_arr.size(), nodes_arr.data());
}
......
This diff is collapsed.
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