Commit bbbfd81c authored by Daniel Clifford's avatar Daniel Clifford Committed by Commit Bot

[torque] Turn implicit converts/unsafe_casts into generics

In the process:
  - Add strict ordering of Types so that name mangling is consistent
    and build time. Previously, the UnionType stored the union's
    types in a std::set<const Type*>, which did not have a consistent
    ordering of the types in the set.
  - Add a int31 type to enable consistency and correctness of
    handling of 'constexpr int31' values on the C++ side.
  - By removing the "implicit" keyword for operators, there is now
    one less difference between operators and calls, another
    incremental step in unifying operators and calls.
  - Enable external (i.e. C++-defined) generic specializations
  - Add CSA support for checking double ElementsKinds, including
    tests.
  - Clean up some constexpr/non-constexpr handling of ElementsKinds.

Bug: v8:7793
Change-Id: I27699aba70b98ebf5466e5b62b045d7b1dad62c8
Reviewed-on: https://chromium-review.googlesource.com/1091155
Commit-Queue: Daniel Clifford <danno@chromium.org>
Reviewed-by: 's avatarTobias Tebbi <tebbi@chromium.org>
Cr-Commit-Position: refs/heads/master@{#53664}
parent 25fbd950
......@@ -529,6 +529,10 @@ module array {
}
type CompareBuiltinFn = builtin(Context, Object, Object, Object) => Number;
extern macro UnsafeCastObjectToCompareBuiltinFn(Object): CompareBuiltinFn;
unsafe_cast<CompareBuiltinFn>(o: Object): CompareBuiltinFn {
return UnsafeCastObjectToCompareBuiltinFn(o);
}
builtin SortCompareDefault(
context: Context, comparefn: Object, x: Object, y: Object): Number {
......@@ -928,14 +932,11 @@ module array {
sort_state[kElementsIdx()] = a.elements;
sort_state[kRandomStateIdx()] = nofNonUndefined;
// TODO(szuend): Extract into IsDoubleElementsKind when bool types are
// fixed in Torque.
if (elementsKind == convert<ElementsKind>(PACKED_DOUBLE_ELEMENTS) ||
elementsKind == convert<ElementsKind>(HOLEY_DOUBLE_ELEMENTS)) {
if (IsDoubleElementsKind(elementsKind)) {
ArrayQuickSort<FastDoubleElements>(
context, sort_state, 0, nofNonUndefined);
} else {
if (elementsKind == convert<ElementsKind>(PACKED_SMI_ELEMENTS)) {
if (elementsKind == PACKED_SMI_ELEMENTS) {
ArrayQuickSort<FastPackedSmiElements>(
context, sort_state, 0, nofNonUndefined);
} else {
......
This diff is collapsed.
......@@ -33,10 +33,6 @@ class DataViewBuiltinsAssembler : public BaseBuiltinsFromDSLAssembler {
return UncheckedCast<Int32T>(
Load(MachineType::Int8(), data_pointer, offset));
}
TNode<Uint32T> UncheckedCastInt32ToUint32(TNode<Int32T> value) {
return Unsigned(value);
}
};
int32_t DataViewElementSize(ElementsKind elements_kind) {
......
......@@ -193,7 +193,7 @@ module data_view {
extern runtime DataViewGetBigUint64(Context, Object, Object, Object): Number;
extern macro ToSmiIndex(Object, Context): Smi labels RangeError;
extern macro DataViewElementSize(constexpr ElementsKind): constexpr int32;
extern macro DataViewElementSize(constexpr ElementsKind): constexpr int31;
macro DataViewGet(context: Context,
receiver: Object,
......@@ -223,7 +223,7 @@ module data_view {
let viewOffset: Smi = data_view.byte_offset;
let viewSize: Smi = data_view.byte_length;
let elementSize: Smi = convert<Smi>(DataViewElementSize(kind));
let elementSize: Smi = DataViewElementSize(kind);
if (getIndex + elementSize > viewSize ||
getIndex + elementSize < getIndex) {
......
......@@ -290,42 +290,41 @@ module typed_array {
let elements_kind: ElementsKind = array.elements_kind;
if (IsElementsKindGreaterThan(elements_kind, UINT32_ELEMENTS)) {
if (elements_kind == convert<ElementsKind>(INT32_ELEMENTS)) {
if (elements_kind == INT32_ELEMENTS) {
loadfn = LoadFixedElement<FixedInt32Array>;
storefn = StoreFixedElement<FixedInt32Array>;
} else if (elements_kind == convert<ElementsKind>(FLOAT32_ELEMENTS)) {
} else if (elements_kind == FLOAT32_ELEMENTS) {
loadfn = LoadFixedElement<FixedFloat32Array>;
storefn = StoreFixedElement<FixedFloat32Array>;
} else if (elements_kind == convert<ElementsKind>(FLOAT64_ELEMENTS)) {
} else if (elements_kind == FLOAT64_ELEMENTS) {
loadfn = LoadFixedElement<FixedFloat64Array>;
storefn = StoreFixedElement<FixedFloat64Array>;
} else if (
elements_kind == convert<ElementsKind>(UINT8_CLAMPED_ELEMENTS)) {
} else if (elements_kind == UINT8_CLAMPED_ELEMENTS) {
loadfn = LoadFixedElement<FixedUint8ClampedArray>;
storefn = StoreFixedElement<FixedUint8ClampedArray>;
} else if (elements_kind == convert<ElementsKind>(BIGUINT64_ELEMENTS)) {
} else if (elements_kind == BIGUINT64_ELEMENTS) {
loadfn = LoadFixedElement<FixedBigUint64Array>;
storefn = StoreFixedElement<FixedBigUint64Array>;
} else if (elements_kind == convert<ElementsKind>(BIGINT64_ELEMENTS)) {
} else if (elements_kind == BIGINT64_ELEMENTS) {
loadfn = LoadFixedElement<FixedBigInt64Array>;
storefn = StoreFixedElement<FixedBigInt64Array>;
} else {
unreachable;
}
} else {
if (elements_kind == convert<ElementsKind>(UINT8_ELEMENTS)) {
if (elements_kind == UINT8_ELEMENTS) {
loadfn = LoadFixedElement<FixedUint8Array>;
storefn = StoreFixedElement<FixedUint8Array>;
} else if (elements_kind == convert<ElementsKind>(INT8_ELEMENTS)) {
} else if (elements_kind == INT8_ELEMENTS) {
loadfn = LoadFixedElement<FixedInt8Array>;
storefn = StoreFixedElement<FixedInt8Array>;
} else if (elements_kind == convert<ElementsKind>(UINT16_ELEMENTS)) {
} else if (elements_kind == UINT16_ELEMENTS) {
loadfn = LoadFixedElement<FixedUint16Array>;
storefn = StoreFixedElement<FixedUint16Array>;
} else if (elements_kind == convert<ElementsKind>(INT16_ELEMENTS)) {
} else if (elements_kind == INT16_ELEMENTS) {
loadfn = LoadFixedElement<FixedInt16Array>;
storefn = StoreFixedElement<FixedInt16Array>;
} else if (elements_kind == convert<ElementsKind>(UINT32_ELEMENTS)) {
} else if (elements_kind == UINT32_ELEMENTS) {
loadfn = LoadFixedElement<FixedUint32Array>;
storefn = StoreFixedElement<FixedUint32Array>;
} else {
......
......@@ -11593,6 +11593,15 @@ Node* CodeStubAssembler::IsFastElementsKind(Node* elements_kind) {
Int32Constant(LAST_FAST_ELEMENTS_KIND));
}
TNode<BoolT> CodeStubAssembler::IsDoubleElementsKind(
TNode<Int32T> elements_kind) {
STATIC_ASSERT(FIRST_ELEMENTS_KIND == FIRST_FAST_ELEMENTS_KIND);
STATIC_ASSERT((PACKED_DOUBLE_ELEMENTS & 1) == 0);
STATIC_ASSERT(PACKED_DOUBLE_ELEMENTS + 1 == HOLEY_DOUBLE_ELEMENTS);
return Word32Equal(Word32Shr(elements_kind, Int32Constant(1)),
Int32Constant(PACKED_DOUBLE_ELEMENTS / 2));
}
Node* CodeStubAssembler::IsFastSmiOrTaggedElementsKind(Node* elements_kind) {
STATIC_ASSERT(FIRST_ELEMENTS_KIND == FIRST_FAST_ELEMENTS_KIND);
STATIC_ASSERT(PACKED_DOUBLE_ELEMENTS > TERMINAL_FAST_ELEMENTS_KIND);
......
......@@ -180,6 +180,24 @@ struct IteratorRecord {
#define CSA_SLOW_ASSERT(csa, ...) ((void)0)
#endif
class int31_t {
public:
int31_t() : value_(0) {}
int31_t(int value) : value_(value) { // NOLINT(runtime/explicit)
DCHECK_EQ((value & 0x80000000) != 0, (value & 0x40000000) != 0);
}
int31_t& operator=(int value) {
DCHECK_EQ((value & 0x80000000) != 0, (value & 0x40000000) != 0);
value_ = value;
return *this;
}
int32_t value() const { return value_; }
operator int32_t() const { return value_; }
private:
int32_t value_;
};
// Provides JavaScript-specific "macro-assembler" functionality on top of the
// CodeAssembler. By factoring the JavaScript-isms out of the CodeAssembler,
// it's possible to add JavaScript-specific useful CodeAssembler "macros"
......@@ -290,6 +308,50 @@ class V8_EXPORT_PRIVATE CodeStubAssembler : public compiler::CodeAssembler {
return CAST(result);
}
TNode<HeapNumber> UnsafeCastNumberToHeapNumber(TNode<Number> p_n) {
return CAST(p_n);
}
TNode<FixedArray> UnsafeCastObjectToFixedArray(TNode<Object> p_o) {
return CAST(p_o);
}
TNode<FixedDoubleArray> UnsafeCastObjectToFixedDoubleArray(
TNode<Object> p_o) {
return CAST(p_o);
}
TNode<HeapNumber> UnsafeCastObjectToHeapNumber(TNode<Object> p_o) {
return CAST(p_o);
}
TNode<HeapObject> UnsafeCastObjectToCallable(TNode<Object> p_o) {
return CAST(p_o);
}
TNode<Smi> UnsafeCastObjectToSmi(TNode<Object> p_o) { return CAST(p_o); }
TNode<Number> UnsafeCastObjectToNumber(TNode<Object> p_o) {
return CAST(p_o);
}
TNode<HeapObject> UnsafeCastObjectToHeapObject(TNode<Object> p_o) {
return CAST(p_o);
}
TNode<JSArray> UnsafeCastObjectToJSArray(TNode<Object> p_o) {
return CAST(p_o);
}
TNode<FixedTypedArrayBase> UnsafeCastObjectToFixedTypedArrayBase(
TNode<Object> p_o) {
return CAST(p_o);
}
TNode<Object> UnsafeCastObjectToCompareBuiltinFn(TNode<Object> p_o) {
return p_o;
}
Node* MatchesParameterMode(Node* value, ParameterMode mode);
#define PARAMETER_BINOP(OpName, IntPtrOpName, SmiOpName) \
......@@ -1638,10 +1700,18 @@ class V8_EXPORT_PRIVATE CodeStubAssembler : public compiler::CodeAssembler {
ParameterMode mode = INTPTR_PARAMETERS);
// ElementsKind helpers:
TNode<BoolT> ElementsKindEqual(TNode<Int32T> a, TNode<Int32T> b) {
return Word32Equal(a, b);
}
bool ElementsKindEqual(ElementsKind a, ElementsKind b) { return a == b; }
Node* IsFastElementsKind(Node* elements_kind);
bool IsFastElementsKind(ElementsKind kind) {
return v8::internal::IsFastElementsKind(kind);
}
TNode<BoolT> IsDoubleElementsKind(TNode<Int32T> elements_kind);
bool IsDoubleElementsKind(ElementsKind kind) {
return v8::internal::IsDoubleElementsKind(kind);
}
Node* IsFastSmiOrTaggedElementsKind(Node* elements_kind);
Node* IsFastSmiElementsKind(Node* elements_kind);
Node* IsHoleyFastElementsKind(Node* elements_kind);
......
......@@ -364,7 +364,10 @@ void Assembler::GetCode(Isolate* isolate, CodeDesc* desc) {
}
}
if (can_opt) {
jump_opt->set_optimizable();
// Disable for now due to bug flushed out by unrelated CSA/Torque
// changes
// TODO(7839): reenable when fixed
// jump_opt->set_optimizable();
}
}
}
......
......@@ -14,11 +14,8 @@ BUILTIN: 'builtin';
RUNTIME: 'runtime';
MODULE: 'module';
JAVASCRIPT: 'javascript';
IMPLICIT: 'implicit';
DEFERRED: 'deferred';
IF: 'if';
UNSAFE_CAST_KEYWORD: 'unsafe_cast';
CONVERT_KEYWORD: 'convert';
FOR: 'for';
WHILE: 'while';
RETURN: 'return';
......@@ -215,8 +212,6 @@ primaryExpression
: helperCall
| DECIMAL_LITERAL
| STRING_LITERAL
| UNSAFE_CAST_KEYWORD '<' type '>' '(' expression ')'
| CONVERT_KEYWORD '<' type '>' '(' expression ')'
| ('(' expression ')');
forInitialization : variableDeclarationWithInitialization?;
......@@ -277,7 +272,7 @@ typeDeclaration : 'type' IDENTIFIER extendsDeclaration? generatesDeclaration? co
typeAliasDeclaration : 'type' IDENTIFIER '=' type ';';
externalBuiltin : EXTERN JAVASCRIPT? BUILTIN IDENTIFIER optionalGenericTypeList '(' typeList ')' optionalType ';';
externalMacro : EXTERN (IMPLICIT? 'operator' STRING_LITERAL)? MACRO IDENTIFIER optionalGenericTypeList typeListMaybeVarArgs optionalType optionalLabelList ';';
externalMacro : EXTERN ('operator' STRING_LITERAL)? MACRO IDENTIFIER optionalGenericTypeList typeListMaybeVarArgs optionalType optionalLabelList ';';
externalRuntime : EXTERN RUNTIME IDENTIFIER typeListMaybeVarArgs optionalType ';';
builtinDeclaration : JAVASCRIPT? BUILTIN IDENTIFIER optionalGenericTypeList parameterList optionalType (helperBody | ';');
genericSpecialization: IDENTIFIER genericSpecializationTypeList parameterList optionalType optionalLabelList helperBody;
......
This diff is collapsed.
......@@ -39,63 +39,60 @@ class TorqueLexer : public antlr4::Lexer {
RUNTIME = 24,
MODULE = 25,
JAVASCRIPT = 26,
IMPLICIT = 27,
DEFERRED = 28,
IF = 29,
UNSAFE_CAST_KEYWORD = 30,
CONVERT_KEYWORD = 31,
FOR = 32,
WHILE = 33,
RETURN = 34,
CONSTEXPR = 35,
CONTINUE = 36,
BREAK = 37,
GOTO = 38,
OTHERWISE = 39,
TRY = 40,
LABEL = 41,
LABELS = 42,
TAIL = 43,
ISNT = 44,
IS = 45,
LET = 46,
EXTERN = 47,
ASSERT_TOKEN = 48,
CHECK_TOKEN = 49,
UNREACHABLE_TOKEN = 50,
DEBUG_TOKEN = 51,
ASSIGNMENT = 52,
ASSIGNMENT_OPERATOR = 53,
EQUAL = 54,
PLUS = 55,
MINUS = 56,
MULTIPLY = 57,
DIVIDE = 58,
MODULO = 59,
BIT_OR = 60,
BIT_AND = 61,
BIT_NOT = 62,
MAX = 63,
MIN = 64,
NOT_EQUAL = 65,
LESS_THAN = 66,
LESS_THAN_EQUAL = 67,
GREATER_THAN = 68,
GREATER_THAN_EQUAL = 69,
SHIFT_LEFT = 70,
SHIFT_RIGHT = 71,
SHIFT_RIGHT_ARITHMETIC = 72,
VARARGS = 73,
EQUALITY_OPERATOR = 74,
INCREMENT = 75,
DECREMENT = 76,
NOT = 77,
STRING_LITERAL = 78,
IDENTIFIER = 79,
WS = 80,
BLOCK_COMMENT = 81,
LINE_COMMENT = 82,
DECIMAL_LITERAL = 83
DEFERRED = 27,
IF = 28,
FOR = 29,
WHILE = 30,
RETURN = 31,
CONSTEXPR = 32,
CONTINUE = 33,
BREAK = 34,
GOTO = 35,
OTHERWISE = 36,
TRY = 37,
LABEL = 38,
LABELS = 39,
TAIL = 40,
ISNT = 41,
IS = 42,
LET = 43,
EXTERN = 44,
ASSERT_TOKEN = 45,
CHECK_TOKEN = 46,
UNREACHABLE_TOKEN = 47,
DEBUG_TOKEN = 48,
ASSIGNMENT = 49,
ASSIGNMENT_OPERATOR = 50,
EQUAL = 51,
PLUS = 52,
MINUS = 53,
MULTIPLY = 54,
DIVIDE = 55,
MODULO = 56,
BIT_OR = 57,
BIT_AND = 58,
BIT_NOT = 59,
MAX = 60,
MIN = 61,
NOT_EQUAL = 62,
LESS_THAN = 63,
LESS_THAN_EQUAL = 64,
GREATER_THAN = 65,
GREATER_THAN_EQUAL = 66,
SHIFT_LEFT = 67,
SHIFT_RIGHT = 68,
SHIFT_RIGHT_ARITHMETIC = 69,
VARARGS = 70,
EQUALITY_OPERATOR = 71,
INCREMENT = 72,
DECREMENT = 73,
NOT = 74,
STRING_LITERAL = 75,
IDENTIFIER = 76,
WS = 77,
BLOCK_COMMENT = 78,
LINE_COMMENT = 79,
DECIMAL_LITERAL = 80
};
explicit TorqueLexer(antlr4::CharStream* input);
......
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -39,63 +39,60 @@ class TorqueParser : public antlr4::Parser {
RUNTIME = 24,
MODULE = 25,
JAVASCRIPT = 26,
IMPLICIT = 27,
DEFERRED = 28,
IF = 29,
UNSAFE_CAST_KEYWORD = 30,
CONVERT_KEYWORD = 31,
FOR = 32,
WHILE = 33,
RETURN = 34,
CONSTEXPR = 35,
CONTINUE = 36,
BREAK = 37,
GOTO = 38,
OTHERWISE = 39,
TRY = 40,
LABEL = 41,
LABELS = 42,
TAIL = 43,
ISNT = 44,
IS = 45,
LET = 46,
EXTERN = 47,
ASSERT_TOKEN = 48,
CHECK_TOKEN = 49,
UNREACHABLE_TOKEN = 50,
DEBUG_TOKEN = 51,
ASSIGNMENT = 52,
ASSIGNMENT_OPERATOR = 53,
EQUAL = 54,
PLUS = 55,
MINUS = 56,
MULTIPLY = 57,
DIVIDE = 58,
MODULO = 59,
BIT_OR = 60,
BIT_AND = 61,
BIT_NOT = 62,
MAX = 63,
MIN = 64,
NOT_EQUAL = 65,
LESS_THAN = 66,
LESS_THAN_EQUAL = 67,
GREATER_THAN = 68,
GREATER_THAN_EQUAL = 69,
SHIFT_LEFT = 70,
SHIFT_RIGHT = 71,
SHIFT_RIGHT_ARITHMETIC = 72,
VARARGS = 73,
EQUALITY_OPERATOR = 74,
INCREMENT = 75,
DECREMENT = 76,
NOT = 77,
STRING_LITERAL = 78,
IDENTIFIER = 79,
WS = 80,
BLOCK_COMMENT = 81,
LINE_COMMENT = 82,
DECIMAL_LITERAL = 83
DEFERRED = 27,
IF = 28,
FOR = 29,
WHILE = 30,
RETURN = 31,
CONSTEXPR = 32,
CONTINUE = 33,
BREAK = 34,
GOTO = 35,
OTHERWISE = 36,
TRY = 37,
LABEL = 38,
LABELS = 39,
TAIL = 40,
ISNT = 41,
IS = 42,
LET = 43,
EXTERN = 44,
ASSERT_TOKEN = 45,
CHECK_TOKEN = 46,
UNREACHABLE_TOKEN = 47,
DEBUG_TOKEN = 48,
ASSIGNMENT = 49,
ASSIGNMENT_OPERATOR = 50,
EQUAL = 51,
PLUS = 52,
MINUS = 53,
MULTIPLY = 54,
DIVIDE = 55,
MODULO = 56,
BIT_OR = 57,
BIT_AND = 58,
BIT_NOT = 59,
MAX = 60,
MIN = 61,
NOT_EQUAL = 62,
LESS_THAN = 63,
LESS_THAN_EQUAL = 64,
GREATER_THAN = 65,
GREATER_THAN_EQUAL = 66,
SHIFT_LEFT = 67,
SHIFT_RIGHT = 68,
SHIFT_RIGHT_ARITHMETIC = 69,
VARARGS = 70,
EQUALITY_OPERATOR = 71,
INCREMENT = 72,
DECREMENT = 73,
NOT = 74,
STRING_LITERAL = 75,
IDENTIFIER = 76,
WS = 77,
BLOCK_COMMENT = 78,
LINE_COMMENT = 79,
DECIMAL_LITERAL = 80
};
enum {
......@@ -731,10 +728,7 @@ class TorqueParser : public antlr4::Parser {
HelperCallContext* helperCall();
antlr4::tree::TerminalNode* DECIMAL_LITERAL();
antlr4::tree::TerminalNode* STRING_LITERAL();
antlr4::tree::TerminalNode* UNSAFE_CAST_KEYWORD();
TypeContext* type();
ExpressionContext* expression();
antlr4::tree::TerminalNode* CONVERT_KEYWORD();
void enterRule(antlr4::tree::ParseTreeListener* listener) override;
void exitRule(antlr4::tree::ParseTreeListener* listener) override;
......@@ -1312,7 +1306,6 @@ class TorqueParser : public antlr4::Parser {
OptionalTypeContext* optionalType();
OptionalLabelListContext* optionalLabelList();
antlr4::tree::TerminalNode* STRING_LITERAL();
antlr4::tree::TerminalNode* IMPLICIT();
void enterRule(antlr4::tree::ParseTreeListener* listener) override;
void exitRule(antlr4::tree::ParseTreeListener* listener) override;
......
......@@ -222,7 +222,6 @@ antlrcpp::Any AstGenerator::visitExternalMacro(
MacroDeclaration* macro = RegisterNode(new ExternalMacroDeclaration{
Pos(context),
context->IDENTIFIER()->getSymbol()->getText(),
context->IMPLICIT() != nullptr,
{},
std::move(
context->typeListMaybeVarArgs()->accept(this).as<ParameterList>()),
......@@ -281,12 +280,12 @@ antlrcpp::Any AstGenerator::visitGenericSpecialization(
auto name = context->IDENTIFIER()->getSymbol()->getText();
auto specialization_parameters =
GetTypeVector(context->genericSpecializationTypeList()->typeList());
Statement* body = context->helperBody()->accept(this).as<Statement*>();
return implicit_cast<Declaration*>(RegisterNode(new SpecializationDeclaration{
Pos(context), name, specialization_parameters,
Pos(context), name, false, specialization_parameters,
GetOptionalParameterList(context->parameterList()),
GetOptionalType(context->optionalType()),
GetOptionalLabelAndTypeList(context->optionalLabelList()), body}));
GetOptionalLabelAndTypeList(context->optionalLabelList()),
context->helperBody()->accept(this).as<Statement*>()}));
}
antlrcpp::Any AstGenerator::visitConstDeclaration(
......@@ -538,14 +537,6 @@ antlrcpp::Any AstGenerator::visitPrimaryExpression(
if (auto* e = context->STRING_LITERAL())
return implicit_cast<Expression*>(RegisterNode(
new StringLiteralExpression{Pos(context), e->getSymbol()->getText()}));
if (context->CONVERT_KEYWORD())
return implicit_cast<Expression*>(RegisterNode(new ConvertExpression{
Pos(context), GetType(context->type()),
context->expression()->accept(this).as<Expression*>()}));
if (context->UNSAFE_CAST_KEYWORD())
return implicit_cast<Expression*>(RegisterNode(new UnsafeCastExpression{
Pos(context), GetType(context->type()),
context->expression()->accept(this).as<Expression*>()}));
return context->expression()->accept(this);
}
......
......@@ -38,9 +38,7 @@ DECLARE_CONTEXTUAL_VARIABLE(CurrentSourcePosition, SourcePosition)
V(FieldAccessExpression) \
V(ElementAccessExpression) \
V(AssignmentExpression) \
V(IncrementDecrementExpression) \
V(UnsafeCastExpression) \
V(ConvertExpression)
V(IncrementDecrementExpression)
#define AST_TYPE_EXPRESSION_NODE_KIND_LIST(V) \
V(BasicTypeExpression) \
......@@ -301,22 +299,6 @@ struct NumberLiteralExpression : Expression {
std::string number;
};
struct ConvertExpression : Expression {
DEFINE_AST_NODE_LEAF_BOILERPLATE(ConvertExpression)
ConvertExpression(SourcePosition p, TypeExpression* t, Expression* v)
: Expression(kKind, p), type(t), value(v) {}
TypeExpression* type;
Expression* value;
};
struct UnsafeCastExpression : Expression {
DEFINE_AST_NODE_LEAF_BOILERPLATE(UnsafeCastExpression)
UnsafeCastExpression(SourcePosition p, TypeExpression* t, Expression* v)
: Expression(kKind, p), type(t), value(v) {}
TypeExpression* type;
Expression* value;
};
struct ElementAccessExpression : LocationExpression {
DEFINE_AST_NODE_LEAF_BOILERPLATE(ElementAccessExpression)
ElementAccessExpression(SourcePosition p, Expression* a, Expression* i)
......@@ -591,27 +573,26 @@ struct CallableNode : AstNode {
struct MacroDeclaration : CallableNode {
DEFINE_AST_NODE_INNER_BOILERPLATE(MacroDeclaration)
MacroDeclaration(AstNode::Kind kind, SourcePosition p, std::string n, bool i,
MacroDeclaration(AstNode::Kind kind, SourcePosition p, std::string n,
base::Optional<std::string> o, ParameterList pl,
TypeExpression* r, const LabelAndTypesVector& l)
: CallableNode(kind, p, n, pl, r, l), implicit(i), op(std::move(o)) {}
bool implicit;
: CallableNode(kind, p, n, pl, r, l), op(std::move(o)) {}
base::Optional<std::string> op;
};
struct ExternalMacroDeclaration : MacroDeclaration {
DEFINE_AST_NODE_LEAF_BOILERPLATE(ExternalMacroDeclaration)
ExternalMacroDeclaration(SourcePosition p, std::string n, bool i,
ExternalMacroDeclaration(SourcePosition p, std::string n,
base::Optional<std::string> o, ParameterList pl,
TypeExpression* r, const LabelAndTypesVector& l)
: MacroDeclaration(kKind, p, n, i, o, pl, r, l) {}
: MacroDeclaration(kKind, p, n, o, pl, r, l) {}
};
struct TorqueMacroDeclaration : MacroDeclaration {
DEFINE_AST_NODE_LEAF_BOILERPLATE(TorqueMacroDeclaration)
TorqueMacroDeclaration(SourcePosition p, std::string n, ParameterList pl,
TypeExpression* r, const LabelAndTypesVector& l)
: MacroDeclaration(kKind, p, n, false, {}, pl, r, l) {}
: MacroDeclaration(kKind, p, n, {}, pl, r, l) {}
};
struct BuiltinDeclaration : CallableNode {
......@@ -666,16 +647,18 @@ struct GenericDeclaration : Declaration {
struct SpecializationDeclaration : Declaration {
DEFINE_AST_NODE_LEAF_BOILERPLATE(SpecializationDeclaration)
SpecializationDeclaration(SourcePosition p, std::string n,
SpecializationDeclaration(SourcePosition p, std::string n, bool e,
std::vector<TypeExpression*> gp, ParameterList pl,
TypeExpression* r, LabelAndTypesVector l,
Statement* b)
: Declaration(kKind, p),
name(std::move(n)),
external(e),
generic_parameters(gp),
signature(new CallableNodeSignature{pl, r, l}),
body(b) {}
std::string name;
bool external;
std::vector<TypeExpression*> generic_parameters;
std::unique_ptr<CallableNodeSignature> signature;
Statement* body;
......
......@@ -140,20 +140,6 @@ void DeclarationVisitor::Visit(ExternalMacroDeclaration* decl,
}
i->second.push_back(handler);
}
if (decl->implicit) {
if (!decl->op || *decl->op != "convert<>") {
ReportError("implicit can only be used with cast<> operator");
}
const TypeVector& parameter_types = signature.parameter_types.types;
if (parameter_types.size() != 1 || signature.parameter_types.var_args) {
ReportError(
"implicit cast operators doesn't only have a single parameter");
}
TypeOracle::RegisterImplicitConversion(signature.return_type,
parameter_types[0]);
}
}
void DeclarationVisitor::Visit(TorqueBuiltinDeclaration* decl,
......@@ -185,7 +171,9 @@ void DeclarationVisitor::Visit(TorqueMacroDeclaration* decl,
}
PushControlSplit();
Visit(body);
if (body != nullptr) {
Visit(body);
}
auto changed_vars = PopControlSplit();
global_context_.AddControlSplitChangedVariables(
decl, declarations()->GetCurrentSpecializationTypeNamesVector(),
......@@ -202,8 +190,14 @@ void DeclarationVisitor::Visit(GenericDeclaration* decl) {
}
void DeclarationVisitor::Visit(SpecializationDeclaration* decl) {
GenericList* generic_list = declarations()->LookupGeneric(decl->name);
if ((decl->body != nullptr) == decl->external) {
std::stringstream stream;
stream << "specialization of " << decl->name
<< " must either be marked 'extern' or have a body";
ReportError(stream.str());
}
GenericList* generic_list = declarations()->LookupGeneric(decl->name);
// Find the matching generic specialization based on the concrete parameter
// list.
CallableNode* matching_callable = nullptr;
......
......@@ -59,8 +59,6 @@ class DeclarationVisitor : public FileVisitor {
Visit(expr->index);
}
void Visit(FieldAccessExpression* expr) { Visit(expr->object); }
void Visit(UnsafeCastExpression* expr) { Visit(expr->value); }
void Visit(ConvertExpression* expr) { Visit(expr->value); }
void Visit(BlockStatement* expr) {
Declarations::NodeScopeActivator scope(declarations(), expr);
for (Statement* stmt : expr->statements) Visit(stmt);
......@@ -344,11 +342,13 @@ class DeclarationVisitor : public FileVisitor {
}
void DeclareSignature(const Signature& signature) {
auto name_iterator = signature.parameter_names.begin();
for (auto t : signature.types()) {
const std::string& name(*name_iterator++);
declarations()->DeclareParameter(name, GetParameterVariableFromName(name),
t);
auto type_iterator = signature.parameter_types.types.begin();
for (auto name : signature.parameter_names) {
const Type* t(*type_iterator++);
if (name.size() != 0) {
declarations()->DeclareParameter(name,
GetParameterVariableFromName(name), t);
}
}
for (auto& label : signature.labels) {
auto label_params = label.types;
......
......@@ -145,9 +145,9 @@ Label* Declarations::LookupLabel(const std::string& name) {
return Label::cast(d);
}
Macro* Declarations::LookupMacro(const std::string& name,
const TypeVector& types) {
Declarable* declarable = Lookup(name);
Macro* Declarations::TryLookupMacro(const std::string& name,
const TypeVector& types) {
Declarable* declarable = TryLookup(name);
if (declarable != nullptr) {
if (declarable->IsMacroList()) {
for (auto& m : MacroList::cast(declarable)->list()) {
......@@ -158,6 +158,13 @@ Macro* Declarations::LookupMacro(const std::string& name,
}
}
}
return nullptr;
}
Macro* Declarations::LookupMacro(const std::string& name,
const TypeVector& types) {
Macro* result = TryLookupMacro(name, types);
if (result != nullptr) return result;
std::stringstream stream;
stream << "macro " << name << " with parameter types " << types
<< " is not defined";
......@@ -337,6 +344,16 @@ TypeVector Declarations::GetCurrentSpecializationTypeNamesVector() {
return result;
}
std::string GetGeneratedCallableName(const std::string& name,
const TypeVector& specialized_types) {
std::string result = name;
for (auto type : specialized_types) {
std::string type_string = type->MangledName();
result += std::to_string(type_string.size()) + type_string;
}
return result;
}
} // namespace torque
} // namespace internal
} // namespace v8
......@@ -15,6 +15,8 @@ namespace v8 {
namespace internal {
namespace torque {
static constexpr const char* const kFromConstexprMacroName = "from_constexpr";
class Declarations {
public:
Declarations()
......@@ -58,6 +60,7 @@ class Declarations {
Value* LookupValue(const std::string& name);
Macro* TryLookupMacro(const std::string& name, const TypeVector& types);
Macro* LookupMacro(const std::string& name, const TypeVector& types);
Builtin* LookupBuiltin(const std::string& name);
......@@ -199,6 +202,9 @@ class Declarations::ScopedGenericScopeChainSnapshot {
ScopeChain::ScopedSnapshotRestorer restorer_;
};
std::string GetGeneratedCallableName(const std::string& name,
const TypeVector& specialized_types);
} // namespace torque
} // namespace internal
} // namespace v8
......
......@@ -25,16 +25,6 @@ Signature FileVisitor::MakeSignature(const CallableNodeSignature* signature) {
return result;
}
std::string FileVisitor::GetGeneratedCallableName(
const std::string& name, const TypeVector& specialized_types) {
std::string result = name;
for (auto type : specialized_types) {
std::string type_string = type->MangledName();
result += std::to_string(type_string.size()) + type_string;
}
return result;
}
Callable* FileVisitor::LookupCall(const std::string& name,
const TypeVector& parameter_types) {
Callable* result = nullptr;
......
......@@ -72,9 +72,6 @@ class FileVisitor {
Signature MakeSignature(const CallableNodeSignature* signature);
std::string GetGeneratedCallableName(const std::string& name,
const TypeVector& specialized_types);
struct PendingSpecialization {
SpecializationKey key;
CallableNode* callable;
......
......@@ -160,67 +160,69 @@ void ImplementationVisitor::Visit(TorqueMacroDeclaration* decl,
CurrentCallableActivator activator(global_context_, macro, decl);
header_out() << " ";
GenerateMacroFunctionDeclaration(header_out(), "", macro);
header_out() << ";" << std::endl;
GenerateMacroFunctionDeclaration(
source_out(), GetDSLAssemblerName(CurrentModule()) + "::", macro);
source_out() << " {" << std::endl;
const Variable* result_var = nullptr;
if (macro->HasReturnValue()) {
const Type* return_type = macro->signature().return_type;
if (!return_type->IsConstexpr()) {
GenerateIndent();
source_out() << "Node* return_default = &*SmiConstant(0);" << std::endl;
if (body != nullptr) {
header_out() << " ";
GenerateMacroFunctionDeclaration(header_out(), "", macro);
header_out() << ";" << std::endl;
GenerateMacroFunctionDeclaration(
source_out(), GetDSLAssemblerName(CurrentModule()) + "::", macro);
source_out() << " {" << std::endl;
const Variable* result_var = nullptr;
if (macro->HasReturnValue()) {
const Type* return_type = macro->signature().return_type;
if (!return_type->IsConstexpr()) {
GenerateIndent();
source_out() << "Node* return_default = &*SmiConstant(0);" << std::endl;
}
VisitResult init = {return_type,
return_type->IsConstexpr()
? (return_type->GetGeneratedTypeName() + "()")
: (std::string("UncheckedCast<") +
return_type->GetGeneratedTNodeTypeName() +
">(return_default)")};
result_var =
GenerateVariableDeclaration(decl, kReturnValueVariable, {}, init);
}
VisitResult init = {
return_type,
return_type->IsConstexpr()
? (return_type->GetGeneratedTypeName() + "()")
: (std::string("UncheckedCast<") +
return_type->GetGeneratedTNodeTypeName() + ">(return_default)")};
result_var =
GenerateVariableDeclaration(decl, kReturnValueVariable, {}, init);
}
Label* macro_end = declarations()->DeclareLabel("macro_end");
GenerateLabelDefinition(macro_end, decl);
const Type* result = Visit(body);
if (result->IsNever()) {
if (!macro->signature().return_type->IsNever() && !macro->HasReturns()) {
std::stringstream s;
s << "macro " << decl->name
<< " that never returns must have return type never";
ReportError(s.str());
Label* macro_end = declarations()->DeclareLabel("macro_end");
GenerateLabelDefinition(macro_end, decl);
const Type* result = Visit(body);
if (result->IsNever()) {
if (!macro->signature().return_type->IsNever() && !macro->HasReturns()) {
std::stringstream s;
s << "macro " << decl->name
<< " that never returns must have return type never";
ReportError(s.str());
}
} else {
if (macro->signature().return_type->IsNever()) {
std::stringstream s;
s << "macro " << decl->name
<< " has implicit return at end of its declartion but return type "
"never";
ReportError(s.str());
} else if (!macro->signature().return_type->IsVoid()) {
std::stringstream s;
s << "macro " << decl->name
<< " expects to return a value but doesn't on all paths";
ReportError(s.str());
}
}
} else {
if (macro->signature().return_type->IsNever()) {
std::stringstream s;
s << "macro " << decl->name
<< " has implicit return at end of its declartion but return type "
"never";
ReportError(s.str());
} else if (!macro->signature().return_type->IsVoid()) {
std::stringstream s;
s << "macro " << decl->name
<< " expects to return a value but doesn't on all paths";
ReportError(s.str());
if (macro->HasReturns()) {
if (!result->IsNever()) {
GenerateLabelGoto(macro_end);
}
GenerateLabelBind(macro_end);
}
}
if (macro->HasReturns()) {
if (!result->IsNever()) {
GenerateLabelGoto(macro_end);
if (result_var != nullptr) {
GenerateIndent();
source_out() << "return " << result_var->GetValueForRead() << ";"
<< std::endl;
}
GenerateLabelBind(macro_end);
source_out() << "}" << std::endl << std::endl;
}
if (result_var != nullptr) {
GenerateIndent();
source_out() << "return " << result_var->GetValueForRead() << ";"
<< std::endl;
}
source_out() << "}" << std::endl << std::endl;
}
void ImplementationVisitor::Visit(TorqueBuiltinDeclaration* decl,
......@@ -520,28 +522,6 @@ VisitResult ImplementationVisitor::Visit(IdentifierExpression* expr) {
return GenerateFetchFromLocation(expr, GetLocationReference(expr));
}
VisitResult ImplementationVisitor::Visit(UnsafeCastExpression* expr) {
const Type* type = declarations()->GetType(expr->type);
if (type->IsConstexpr()) {
ReportError("unsafe_cast can only be used for non constexpr types.");
}
VisitResult result = Visit(expr->value);
std::string result_variable_name = GenerateNewTempVariable(type);
source_out() << "CAST(";
source_out() << result.variable();
source_out() << ");\n";
return VisitResult{type, result_variable_name};
}
VisitResult ImplementationVisitor::Visit(ConvertExpression* expr) {
Arguments args;
args.parameters = {Visit(expr->value)};
return GenerateOperation("convert<>", args,
declarations()->GetType(expr->type));
}
const Type* ImplementationVisitor::Visit(GotoStatement* stmt) {
Label* label = declarations()->LookupLabel(stmt->label);
......@@ -1632,11 +1612,11 @@ VisitResult ImplementationVisitor::GenerateImplicitConvert(
if (destination_type == source.type()) {
return source;
}
if (TypeOracle::IsImplicitlyConverableFrom(destination_type, source.type())) {
VisitResult result(source.type(), source.variable());
Arguments args;
args.parameters = {result};
return GenerateOperation("convert<>", args, destination_type);
std::string name =
GetGeneratedCallableName(kFromConstexprMacroName, {destination_type});
return GenerateCall(name, {{source}, {}}, false);
} else if (IsAssignableFrom(destination_type, source.type())) {
return VisitResult(destination_type, source.variable());
} else {
......
......@@ -83,9 +83,6 @@ class ImplementationVisitor : public FileVisitor {
return GenerateFetchFromLocation(expr, GetLocationReference(expr));
}
VisitResult Visit(UnsafeCastExpression* expr);
VisitResult Visit(ConvertExpression* expr);
void Visit(ModuleDeclaration* decl);
void Visit(DefaultModuleDeclaration* decl) {
Visit(implicit_cast<ModuleDeclaration*>(decl));
......
......@@ -20,10 +20,6 @@ class TypeOracle : public ContextualClass<TypeOracle> {
explicit TypeOracle(Declarations* declarations)
: declarations_(declarations) {}
static void RegisterImplicitConversion(const Type* to, const Type* from) {
Get().implicit_conversions_.push_back(std::make_pair(to, from));
}
static const Type* GetArgumentsType() {
return Get().GetBuiltinType(ARGUMENTS_TYPE_STRING);
}
......@@ -61,12 +57,8 @@ class TypeOracle : public ContextualClass<TypeOracle> {
}
static bool IsImplicitlyConverableFrom(const Type* to, const Type* from) {
for (auto& conversion : Get().implicit_conversions_) {
if (conversion.first == to && conversion.second == from) {
return true;
}
}
return false;
std::string name = GetGeneratedCallableName(kFromConstexprMacroName, {to});
return Get().declarations_->TryLookupMacro(name, {from}) != nullptr;
}
private:
......@@ -75,7 +67,6 @@ class TypeOracle : public ContextualClass<TypeOracle> {
}
Declarations* declarations_;
std::vector<std::pair<const Type*, const Type*>> implicit_conversions_;
};
} // namespace torque
......
......@@ -223,6 +223,10 @@ bool IsCompatibleSignature(const ParameterTypes& to, const TypeVector& from) {
return true;
}
bool operator<(const Type& a, const Type& b) {
return a.MangledName() < b.MangledName();
}
} // namespace torque
} // namespace internal
} // namespace v8
......@@ -5,6 +5,7 @@
#ifndef V8_TORQUE_TYPES_H_
#define V8_TORQUE_TYPES_H_
#include <algorithm>
#include <set>
#include <string>
#include <vector>
......@@ -175,6 +176,13 @@ class FunctionPointerType final : public Type {
const Type* const return_type_;
};
bool operator<(const Type& a, const Type& b);
struct TypeLess {
bool operator()(const Type* const a, const Type* const b) const {
return *a < *b;
}
};
class UnionType final : public Type {
public:
DECLARE_TYPE_BOILERPLATE(UnionType);
......@@ -257,7 +265,7 @@ class UnionType final : public Type {
private:
explicit UnionType(const Type* t) : Type(Kind::kUnionType, t), types_({t}) {}
std::set<const Type*> types_;
std::set<const Type*, TypeLess> types_;
};
inline std::ostream& operator<<(std::ostream& os, const Type* t) {
......
......@@ -3311,6 +3311,55 @@ TEST(SingleInputPhiElimination) {
// single-input phi is properly eliminated.
}
TEST(IsDoubleElementsKind) {
Isolate* isolate(CcTest::InitIsolateOnce());
const int kNumParams = 2;
CodeAssemblerTester ft_tester(isolate, kNumParams);
{
CodeStubAssembler m(ft_tester.state());
m.Return(m.SmiFromInt32(m.UncheckedCast<Int32T>(
m.IsDoubleElementsKind(m.SmiToInt32(m.Parameter(0))))));
}
FunctionTester ft(ft_tester.GenerateCode(), kNumParams);
CHECK_EQ(
(*Handle<Smi>::cast(
ft.Call(Handle<Smi>(Smi::FromInt(PACKED_DOUBLE_ELEMENTS), isolate))
.ToHandleChecked()))
->value(),
1);
CHECK_EQ(
(*Handle<Smi>::cast(
ft.Call(Handle<Smi>(Smi::FromInt(HOLEY_DOUBLE_ELEMENTS), isolate))
.ToHandleChecked()))
->value(),
1);
CHECK_EQ((*Handle<Smi>::cast(
ft.Call(Handle<Smi>(Smi::FromInt(HOLEY_ELEMENTS), isolate))
.ToHandleChecked()))
->value(),
0);
CHECK_EQ((*Handle<Smi>::cast(
ft.Call(Handle<Smi>(Smi::FromInt(PACKED_ELEMENTS), isolate))
.ToHandleChecked()))
->value(),
0);
CHECK_EQ((*Handle<Smi>::cast(
ft.Call(Handle<Smi>(Smi::FromInt(PACKED_SMI_ELEMENTS), isolate))
.ToHandleChecked()))
->value(),
0);
CHECK_EQ((*Handle<Smi>::cast(
ft.Call(Handle<Smi>(Smi::FromInt(HOLEY_SMI_ELEMENTS), isolate))
.ToHandleChecked()))
->value(),
0);
CHECK_EQ((*Handle<Smi>::cast(
ft.Call(Handle<Smi>(Smi::FromInt(DICTIONARY_ELEMENTS), isolate))
.ToHandleChecked()))
->value(),
0);
}
} // namespace compiler
} // namespace internal
} // namespace v8
......@@ -36,7 +36,7 @@ module test {
}
macro TestConstexpr1() {
check(convert<bool>(IsFastElementsKind(PACKED_SMI_ELEMENTS)));
check(from_constexpr<bool>(IsFastElementsKind(PACKED_SMI_ELEMENTS)));
}
macro TestConstexprIf() {
......@@ -46,10 +46,10 @@ module test {
}
macro TestConstexprReturn() {
check(convert<bool>(ElementsKindTestHelper3(UINT8_ELEMENTS)));
check(convert<bool>(ElementsKindTestHelper3(UINT16_ELEMENTS)));
check(!convert<bool>(ElementsKindTestHelper3(UINT32_ELEMENTS)));
check(convert<bool>(!ElementsKindTestHelper3(UINT32_ELEMENTS)));
check(from_constexpr<bool>(ElementsKindTestHelper3(UINT8_ELEMENTS)));
check(from_constexpr<bool>(ElementsKindTestHelper3(UINT16_ELEMENTS)));
check(!from_constexpr<bool>(ElementsKindTestHelper3(UINT32_ELEMENTS)));
check(from_constexpr<bool>(!ElementsKindTestHelper3(UINT32_ELEMENTS)));
}
macro TestGotoLabel(): Boolean {
......
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