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

[torque] Implement transient types and checking

In the process implement TopType to express undefined values and
transient types after they no longer are valid, as well as checks to
make sure that transtioning callables are transitively marked
to express if they or their call chain modify transient types.

Bug: v8:7793
Change-Id: Idb237e878d3a511a4f460b6510ffd4876593951d
Reviewed-on: https://chromium-review.googlesource.com/c/1297963
Commit-Queue: Daniel Clifford <danno@chromium.org>
Reviewed-by: 's avatarTobias Tebbi <tebbi@chromium.org>
Cr-Commit-Position: refs/heads/master@{#57052}
parent 61c6404e
......@@ -8,7 +8,7 @@ module array {
}
// https://tc39.github.io/ecma262/#sec-array.prototype.copyWithin
javascript builtin ArrayPrototypeCopyWithin(
transitioning javascript builtin ArrayPrototypeCopyWithin(
context: Context, receiver: Object, ...arguments): Object {
// 1. Let O be ? ToObject(this value).
const object: JSReceiver = ToObject_Inline(context, receiver);
......
......@@ -3,7 +3,7 @@
// found in the LICENSE file.
module array {
macro ArrayForEachTorqueContinuation(
transitioning macro ArrayForEachTorqueContinuation(
context: Context, o: JSReceiver, len: Number, callbackfn: Callable,
thisArg: Object, initialK: Number): Object {
// 5. Let k be 0.
......@@ -30,7 +30,7 @@ module array {
return Undefined;
}
javascript builtin ArrayForEachLoopEagerDeoptContinuation(
transitioning javascript builtin ArrayForEachLoopEagerDeoptContinuation(
context: Context, receiver: Object, callback: Object, thisArg: Object,
initialK: Object, length: Object): Object {
// The unsafe Cast is safe because all continuation points in forEach are
......@@ -42,7 +42,7 @@ module array {
length, Undefined);
}
javascript builtin ArrayForEachLoopLazyDeoptContinuation(
transitioning javascript builtin ArrayForEachLoopLazyDeoptContinuation(
context: Context, receiver: Object, callback: Object, thisArg: Object,
initialK: Object, length: Object, result: Object): Object {
// The unsafe Cast is safe because all continuation points in forEach are
......@@ -54,7 +54,7 @@ module array {
length, Undefined);
}
builtin ArrayForEachLoopContinuation(
transitioning builtin ArrayForEachLoopContinuation(
context: Context, receiver: JSReceiver, callback: Object, thisArg: Object,
array: Object, object: Object, initialK: Object, length: Object,
to: Object): Object {
......@@ -72,7 +72,7 @@ module array {
}
}
macro VisitAllElements<FixedArrayType: type>(
transitioning macro VisitAllElements<FixedArrayType: type>(
context: Context, a: JSArray, len: Smi, callbackfn: Callable,
thisArg: Object): void
labels Bailout(Smi) {
......@@ -106,7 +106,7 @@ module array {
}
}
macro FastArrayForEach(
transitioning macro FastArrayForEach(
context: Context, o: JSReceiver, len: Number, callbackfn: Callable,
thisArg: Object): Object
labels Bailout(Smi) {
......@@ -136,7 +136,7 @@ module array {
}
// https://tc39.github.io/ecma262/#sec-array.prototype.foreach
javascript builtin ArrayForEach(
transitioning javascript builtin ArrayForEach(
context: Context, receiver: Object, ...arguments): Object {
try {
if (IsNullOrUndefined(receiver)) {
......
......@@ -15,7 +15,7 @@ module array {
String
labels IfException(Object);
builtin LoadJoinElement<T: type>(
transitioning builtin LoadJoinElement<T: type>(
context: Context, receiver: JSReceiver, k: Number): Object {
return GetProperty(receiver, k);
}
......@@ -59,7 +59,7 @@ module array {
}
}
builtin ConvertToLocaleString(
transitioning builtin ConvertToLocaleString(
context: Context, element: Object, locales: Object,
options: Object): String {
if (IsNullOrUndefined(element)) return kEmptyString;
......@@ -211,7 +211,7 @@ module array {
buffer.fixedArray, buffer.index, sep, r);
}
macro ArrayJoinImpl(
transitioning macro ArrayJoinImpl(
context: Context, receiver: JSReceiver, sep: String, lengthNumber: Number,
useToLocaleString: constexpr bool, locales: Object, options: Object,
initialLoadJoinElement: LoadJoinElementFn): String {
......@@ -279,7 +279,7 @@ module array {
return BufferJoin(buffer, sep);
}
macro ArrayJoin(implicit context: Context)(
transitioning macro ArrayJoin(implicit context: Context)(
useToLocaleString: constexpr bool, receiver: JSReceiver, sep: String,
lenNumber: Number, locales: Object, options: Object): Object {
const map: Map = receiver.map;
......@@ -327,13 +327,13 @@ module array {
loadJoinElements);
}
builtin ArrayJoinWithToLocaleString(
transitioning builtin ArrayJoinWithToLocaleString(
context: Context, receiver: JSReceiver, sep: String, len: Number,
locales: Object, options: Object): Object {
return ArrayJoin(true, receiver, sep, len, locales, options);
}
builtin ArrayJoinWithoutToLocaleString(
transitioning builtin ArrayJoinWithoutToLocaleString(
context: Context, receiver: JSReceiver, sep: String, len: Number,
locales: Object, options: Object): Object {
return ArrayJoin(false, receiver, sep, len, locales, options);
......@@ -450,7 +450,7 @@ module array {
}
// Main entry point for all builtins using Array Join functionality.
macro CycleProtectedArrayJoin(implicit context: Context)(
transitioning macro CycleProtectedArrayJoin(implicit context: Context)(
useToLocaleString: constexpr bool, receiver: Object, sepObj: Object,
locales: Object, options: Object): Object {
// 1. Let O be ? ToObject(this value).
......@@ -485,7 +485,7 @@ module array {
}
// https://tc39.github.io/ecma262/#sec-array.prototype.join
javascript builtin ArrayPrototypeJoin(
transitioning javascript builtin ArrayPrototypeJoin(
context: Context, receiver: Object, ...arguments): Object {
const separator: Object = arguments[0];
return CycleProtectedArrayJoin(
......@@ -493,7 +493,7 @@ module array {
}
// https://tc39.github.io/ecma262/#sec-array.prototype.toLocaleString
javascript builtin ArrayPrototypeToLocaleString(
transitioning javascript builtin ArrayPrototypeToLocaleString(
context: Context, receiver: Object, ...arguments): Object {
const locales: Object = arguments[0];
const options: Object = arguments[1];
......@@ -501,7 +501,7 @@ module array {
}
// https://tc39.github.io/ecma262/#sec-array.prototype.toString
javascript builtin ArrayPrototypeToString(
transitioning javascript builtin ArrayPrototypeToString(
context: Context, receiver: Object, ...arguments): Object {
// 1. Let array be ? ToObject(this value).
const array: JSReceiver = ToObject_Inline(context, receiver);
......
......@@ -90,7 +90,7 @@ module array {
context, array, length, fromSmi, searchElement);
}
macro GenericArrayLastIndexOf(
transitioning macro GenericArrayLastIndexOf(
context: Context, object: JSReceiver, searchElement: Object,
from: Number): Object {
let k: Number = from;
......@@ -122,7 +122,7 @@ module array {
}
// https://tc39.github.io/ecma262/#sec-array.prototype.lastIndexOf
javascript builtin ArrayPrototypeLastIndexOf(
transitioning javascript builtin ArrayPrototypeLastIndexOf(
context: Context, receiver: Object, ...arguments): Object {
// 1. Let O be ? ToObject(this value).
const object: JSReceiver = ToObject_Inline(context, receiver);
......
......@@ -4,7 +4,7 @@
module array {
// https://tc39.github.io/ecma262/#sec-array.of
javascript builtin ArrayOf(implicit context: Context)(
transitioning javascript builtin ArrayOf(implicit context: Context)(
receiver: Object, ...arguments): Object {
// 1. Let len be the actual number of arguments passed to this function.
const len: Smi = Convert<Smi>(arguments.length);
......
......@@ -72,7 +72,8 @@ module array {
}
}
macro GenericArrayReverse(context: Context, receiver: Object): Object {
transitioning macro GenericArrayReverse(
context: Context, receiver: Object): Object {
// 1. Let O be ? ToObject(this value).
const object: JSReceiver = ToObject_Inline(context, receiver);
......@@ -165,7 +166,7 @@ module array {
}
// https://tc39.github.io/ecma262/#sec-array.prototype.reverse
javascript builtin ArrayPrototypeReverse(
transitioning javascript builtin ArrayPrototypeReverse(
context: Context, receiver: Object, ...arguments): Object {
try {
TryFastPackedArrayReverse(receiver) otherwise Baseline;
......
......@@ -118,7 +118,7 @@ module array {
}
// https://tc39.github.io/ecma262/#sec-array.prototype.slice
javascript builtin ArraySlice(
transitioning javascript builtin ArraySlice(
context: Context, receiver: Object, ...arguments): Object {
// Handle array cloning case if the receiver is a fast array.
if (arguments.length == 0) {
......
......@@ -106,7 +106,7 @@ module array {
a.length = newLength;
}
macro FastArraySplice(
transitioning macro FastArraySplice(
context: Context, args: constexpr Arguments, o: JSReceiver,
originalLengthNumber: Number, actualStartNumber: Number, insertCount: Smi,
actualDeleteCountNumber: Number): Object
......@@ -177,7 +177,7 @@ module array {
return deletedResult;
}
macro FillDeletedElementsArray(
transitioning macro FillDeletedElementsArray(
context: Context, o: JSReceiver, actualStart: Number,
actualDeleteCount: Number, a: JSReceiver): Object {
// 10. Let k be 0.
......@@ -210,7 +210,7 @@ module array {
// HandleForwardCase implements step 15. "If itemCount < actualDeleteCount,
// then...""
macro HandleForwardCase(
transitioning macro HandleForwardCase(
context: Context, o: JSReceiver, len: Number, itemCount: Number,
actualStart: Number, actualDeleteCount: Number): void {
// 15. If itemCount < actualDeleteCount, then
......@@ -258,7 +258,7 @@ module array {
// HandleBackwardCase implements step 16. "Else if itemCount >
// actualDeleteCount, then..."
macro HandleBackwardCase(
transitioning macro HandleBackwardCase(
context: Context, o: JSReceiver, len: Number, itemCount: Number,
actualStart: Number, actualDeleteCount: Number): void {
// 16. Else if itemCount > actualDeleteCount, then
......@@ -295,7 +295,7 @@ module array {
}
}
macro SlowSplice(
transitioning macro SlowSplice(
context: Context, arguments: constexpr Arguments, o: JSReceiver,
len: Number, actualStart: Number, insertCount: Smi,
actualDeleteCount: Number): Object {
......@@ -349,7 +349,7 @@ module array {
}
// https://tc39.github.io/ecma262/#sec-array.prototype.splice
javascript builtin ArraySplice(
transitioning javascript builtin ArraySplice(
context: Context, receiver: Object, ...arguments): Object {
// 1. Let O be ? ToObject(this value).
const o: JSReceiver = ToObject(context, receiver);
......
......@@ -21,7 +21,7 @@ module array {
Convert<int32>(arguments.length));
}
macro GenericArrayUnshift(
transitioning macro GenericArrayUnshift(
context: Context, receiver: Object,
arguments: constexpr Arguments): Number {
// 1. Let O be ? ToObject(this value).
......@@ -94,7 +94,7 @@ module array {
}
// https://tc39.github.io/ecma262/#sec-array.prototype.unshift
javascript builtin ArrayPrototypeUnshift(
transitioning javascript builtin ArrayPrototypeUnshift(
context: Context, receiver: Object, ...arguments): Object {
try {
TryFastArrayUnshift(context, receiver, arguments) otherwise Baseline;
......
......@@ -41,9 +41,9 @@ type JSArgumentsObjectWithLength extends JSObject
generates 'TNode<JSArgumentsObjectWithLength>';
type JSArray extends JSArgumentsObjectWithLength
generates 'TNode<JSArray>';
type FastJSArray extends JSArray
transient type FastJSArray extends JSArray
generates 'TNode<JSArray>';
type FastJSArrayForCopy extends FastJSArray
transient type FastJSArrayForCopy extends FastJSArray
generates 'TNode<JSArray>';
type JSFunction extends JSObject generates 'TNode<JSFunction>';
type JSBoundFunction extends JSObject generates 'TNode<JSBoundFunction>';
......@@ -250,13 +250,15 @@ extern macro ToInteger_Inline(
extern macro ToLength_Inline(Context, Object): Number;
extern macro ToNumber_Inline(Context, Object): Number;
extern macro ToString_Inline(Context, Object): String;
extern macro GetProperty(implicit context: Context)(Object, Object): Object;
extern builtin SetProperty(implicit context: Context)(Object, Object, Object);
extern builtin DeleteProperty(implicit context: Context)(
extern transitioning macro GetProperty(implicit context: Context)(
Object, Object): Object;
extern transitioning builtin SetProperty(implicit context: Context)(
Object, Object, Object);
extern transitioning builtin DeleteProperty(implicit context: Context)(
Object, Object, LanguageMode);
extern builtin HasProperty(implicit context: Context)(
extern transitioning builtin HasProperty(implicit context: Context)(
JSReceiver, Object): Boolean;
extern macro HasProperty_Inline(implicit context: Context)(
extern transitioning macro HasProperty_Inline(implicit context: Context)(
JSReceiver, Object): Boolean;
extern macro ThrowRangeError(Context, constexpr MessageTemplate): never;
......@@ -285,9 +287,10 @@ extern macro IsTheHole(Object): bool;
extern macro IsString(HeapObject): bool;
extern builtin ToString(Context, Object): String;
extern runtime NormalizeElements(Context, JSObject);
extern runtime TransitionElementsKindWithKind(Context, JSObject, Smi);
extern runtime CreateDataProperty(implicit context: Context)(
extern transitioning runtime NormalizeElements(Context, JSObject);
extern transitioning runtime TransitionElementsKindWithKind(
Context, JSObject, Smi);
extern transitioning runtime CreateDataProperty(implicit context: Context)(
JSReceiver, Object, Object);
extern macro LoadRoot(constexpr RootIndex): Object;
......@@ -433,7 +436,7 @@ extern operator '!' macro Word32BinaryNot(bool): bool;
extern operator '!' macro IsFalse(Boolean): bool;
extern operator '.map' macro LoadMap(HeapObject): Map;
extern operator '.map=' macro StoreMap(HeapObject, Map);
extern transitioning operator '.map=' macro StoreMap(HeapObject, Map);
extern operator '.instanceType' macro LoadInstanceType(HeapObject):
InstanceType;
......@@ -1015,13 +1018,15 @@ extern macro LoadDoubleWithHoleCheck(FixedDoubleArray, intptr): float64
labels IfHole;
extern macro StoreFixedDoubleArrayHoleSmi(FixedDoubleArray, Smi): void;
extern macro Call(Context, Callable, Object): Object;
extern macro Call(Context, Callable, Object, Object): Object;
extern macro Call(Context, Callable, Object, Object, Object): Object;
extern macro Call(Context, Callable, Object, Object, Object, Object): Object;
extern macro Call(
extern transitioning macro Call(Context, Callable, Object): Object;
extern transitioning macro Call(Context, Callable, Object, Object): Object;
extern transitioning macro Call(
Context, Callable, Object, Object, Object): Object;
extern transitioning macro Call(
Context, Callable, Object, Object, Object, Object): Object;
extern transitioning macro Call(
Context, Callable, Object, Object, Object, Object, Object): Object;
extern macro Call(
extern transitioning macro Call(
Context, Callable, Object, Object, Object, Object, Object, Object): Object;
extern builtin CloneFastJSArray(Context, FastJSArrayForCopy): JSArray;
......@@ -1066,7 +1071,7 @@ macro TorqueCopyElements(
count);
}
macro LoadElementNoHole<T: type>(a: JSArray, index: Smi): Object
transitioning macro LoadElementNoHole<T: type>(a: JSArray, index: Smi): Object
labels IfHole;
LoadElementNoHole<FixedArray>(a: JSArray, index: Smi): Object
......@@ -1154,7 +1159,8 @@ macro ToIndex(input: Object, context: Context): Number
return value;
}
macro GetLengthProperty(implicit context: Context)(o: Object): Number {
transitioning macro GetLengthProperty(implicit context: Context)(o: Object):
Number {
try {
typeswitch (o) {
case (a: JSArray): {
......
......@@ -679,37 +679,52 @@ module data_view {
let littleEndian: bool = ToBoolean(requestedLittleEndian);
let buffer: JSArrayBuffer = dataView.buffer;
let bigIntValue: BigInt;
let numValue: Number;
// According to ES6 section 24.2.1.2 SetViewValue, we must perform
// the conversion before doing the bounds check.
if constexpr (kind == BIGUINT64_ELEMENTS || kind == BIGINT64_ELEMENTS) {
bigIntValue = ToBigInt(context, value);
} else {
numValue = ToNumber(context, value);
}
let bigIntValue: BigInt = ToBigInt(context, value);
if (IsDetachedBuffer(buffer)) {
ThrowTypeError(
context, kDetachedOperation, MakeDataViewSetterNameString(kind));
}
let getIndexFloat: float64 = Convert<float64>(getIndex);
let getIndexWord: uintptr = Convert<uintptr>(getIndexFloat);
if (IsDetachedBuffer(buffer)) {
ThrowTypeError(
context, kDetachedOperation, MakeDataViewSetterNameString(kind));
}
let viewOffsetWord: uintptr = dataView.byte_offset;
let viewSizeFloat: float64 = Convert<float64>(dataView.byte_length);
let elementSizeFloat: float64 = Convert<float64>(DataViewElementSize(kind));
let getIndexFloat: float64 = Convert<float64>(getIndex);
let getIndexWord: uintptr = Convert<uintptr>(getIndexFloat);
if (getIndexFloat + elementSizeFloat > viewSizeFloat) {
ThrowRangeError(context, kInvalidDataViewAccessorOffset);
}
let viewOffsetWord: uintptr = dataView.byte_offset;
let viewSizeFloat: float64 = Convert<float64>(dataView.byte_length);
let elementSizeFloat: float64 =
Convert<float64>(DataViewElementSize(kind));
let bufferIndex: uintptr = getIndexWord + viewOffsetWord;
if (getIndexFloat + elementSizeFloat > viewSizeFloat) {
ThrowRangeError(context, kInvalidDataViewAccessorOffset);
}
if constexpr (kind == BIGUINT64_ELEMENTS || kind == BIGINT64_ELEMENTS) {
let bufferIndex: uintptr = getIndexWord + viewOffsetWord;
StoreDataViewBigInt(buffer, bufferIndex, bigIntValue, littleEndian);
} else {
let numValue: Number = ToNumber(context, value);
if (IsDetachedBuffer(buffer)) {
ThrowTypeError(
context, kDetachedOperation, MakeDataViewSetterNameString(kind));
}
let getIndexFloat: float64 = Convert<float64>(getIndex);
let getIndexWord: uintptr = Convert<uintptr>(getIndexFloat);
let viewOffsetWord: uintptr = dataView.byte_offset;
let viewSizeFloat: float64 = Convert<float64>(dataView.byte_length);
let elementSizeFloat: float64 =
Convert<float64>(DataViewElementSize(kind));
if (getIndexFloat + elementSizeFloat > viewSizeFloat) {
ThrowRangeError(context, kInvalidDataViewAccessorOffset);
}
let bufferIndex: uintptr = getIndexWord + viewOffsetWord;
let doubleValue: float64 = ChangeNumberToFloat64(numValue);
if constexpr (kind == UINT8_ELEMENTS || kind == INT8_ELEMENTS) {
......
......@@ -67,7 +67,7 @@ module typed_array {
return Undefined;
}
macro CallCompareWithDetachedCheck(
transitioning macro CallCompareWithDetachedCheck(
context: Context, array: JSTypedArray, comparefn: Callable, a: Object,
b: Object): Number
labels Detached {
......@@ -86,7 +86,7 @@ module typed_array {
}
// InsertionSort is used for smaller arrays.
macro TypedArrayInsertionSort(
transitioning macro TypedArrayInsertionSort(
context: Context, array: JSTypedArray, fromArg: Smi, toArg: Smi,
comparefn: Callable, load: LoadFn, store: StoreFn)
labels Detached {
......@@ -112,7 +112,7 @@ module typed_array {
}
}
macro TypedArrayQuickSortImpl(
transitioning macro TypedArrayQuickSortImpl(
context: Context, array: JSTypedArray, fromArg: Smi, toArg: Smi,
comparefn: Callable, load: LoadFn, store: StoreFn)
labels Detached {
......@@ -241,7 +241,7 @@ module typed_array {
}
}
builtin TypedArrayQuickSort(
transitioning builtin TypedArrayQuickSort(
context: Context, array: JSTypedArray, from: Smi, to: Smi,
comparefn: Callable, load: LoadFn, store: StoreFn): JSTypedArray {
try {
......@@ -256,7 +256,7 @@ module typed_array {
}
// https://tc39.github.io/ecma262/#sec-%typedarray%.prototype.sort
javascript builtin TypedArrayPrototypeSort(
transitioning javascript builtin TypedArrayPrototypeSort(
context: Context, receiver: Object, ...arguments): JSTypedArray {
// 1. If comparefn is not undefined and IsCallable(comparefn) is false,
// throw a TypeError exception.
......
......@@ -594,16 +594,18 @@ struct BlockStatement : Statement {
struct TypeDeclaration : Declaration {
DEFINE_AST_NODE_LEAF_BOILERPLATE(TypeDeclaration)
TypeDeclaration(SourcePosition pos, std::string name,
TypeDeclaration(SourcePosition pos, std::string name, bool transient,
base::Optional<std::string> extends,
base::Optional<std::string> generates,
base::Optional<std::string> constexpr_generates)
: Declaration(kKind, pos),
name(std::move(name)),
transient(transient),
extends(std::move(extends)),
generates(std::move(generates)),
constexpr_generates(std::move(constexpr_generates)) {}
std::string name;
bool transient;
base::Optional<std::string> extends;
base::Optional<std::string> generates;
base::Optional<std::string> constexpr_generates;
......@@ -637,84 +639,94 @@ struct CallableNodeSignature {
};
struct CallableNode : AstNode {
CallableNode(AstNode::Kind kind, SourcePosition pos, std::string name,
ParameterList parameters, TypeExpression* return_type,
const LabelAndTypesVector& labels)
CallableNode(AstNode::Kind kind, SourcePosition pos, bool transitioning,
std::string name, ParameterList parameters,
TypeExpression* return_type, const LabelAndTypesVector& labels)
: AstNode(kind, pos),
transitioning(transitioning),
name(std::move(name)),
signature(new CallableNodeSignature{parameters, return_type, labels}) {}
DEFINE_AST_NODE_INNER_BOILERPLATE(CallableNode)
bool transitioning;
std::string name;
std::unique_ptr<CallableNodeSignature> signature;
};
struct MacroDeclaration : CallableNode {
DEFINE_AST_NODE_INNER_BOILERPLATE(MacroDeclaration)
MacroDeclaration(AstNode::Kind kind, SourcePosition pos, std::string name,
base::Optional<std::string> op, ParameterList parameters,
TypeExpression* return_type,
MacroDeclaration(AstNode::Kind kind, SourcePosition pos, bool transitioning,
std::string name, base::Optional<std::string> op,
ParameterList parameters, TypeExpression* return_type,
const LabelAndTypesVector& labels)
: CallableNode(kind, pos, std::move(name), std::move(parameters),
return_type, labels),
: CallableNode(kind, pos, transitioning, std::move(name),
std::move(parameters), return_type, labels),
op(std::move(op)) {}
base::Optional<std::string> op;
};
struct ExternalMacroDeclaration : MacroDeclaration {
DEFINE_AST_NODE_LEAF_BOILERPLATE(ExternalMacroDeclaration)
ExternalMacroDeclaration(SourcePosition pos, std::string name,
base::Optional<std::string> op,
ExternalMacroDeclaration(SourcePosition pos, bool transitioning,
std::string name, base::Optional<std::string> op,
ParameterList parameters,
TypeExpression* return_type,
const LabelAndTypesVector& labels)
: MacroDeclaration(kKind, pos, std::move(name), std::move(op),
std::move(parameters), return_type, labels) {}
: MacroDeclaration(kKind, pos, transitioning, std::move(name),
std::move(op), std::move(parameters), return_type,
labels) {}
};
struct TorqueMacroDeclaration : MacroDeclaration {
DEFINE_AST_NODE_LEAF_BOILERPLATE(TorqueMacroDeclaration)
TorqueMacroDeclaration(SourcePosition pos, std::string name,
base::Optional<std::string> op,
TorqueMacroDeclaration(SourcePosition pos, bool transitioning,
std::string name, base::Optional<std::string> op,
ParameterList parameters, TypeExpression* return_type,
const LabelAndTypesVector& labels)
: MacroDeclaration(kKind, pos, std::move(name), std::move(op),
std::move(parameters), return_type, labels) {}
: MacroDeclaration(kKind, pos, transitioning, std::move(name),
std::move(op), std::move(parameters), return_type,
labels) {}
};
struct BuiltinDeclaration : CallableNode {
BuiltinDeclaration(AstNode::Kind kind, SourcePosition pos,
bool javascript_linkage, std::string name,
ParameterList parameters, TypeExpression* return_type)
: CallableNode(kind, pos, std::move(name), std::move(parameters),
return_type, {}),
bool javascript_linkage, bool transitioning,
std::string name, ParameterList parameters,
TypeExpression* return_type)
: CallableNode(kind, pos, transitioning, std::move(name),
std::move(parameters), return_type, {}),
javascript_linkage(javascript_linkage) {}
bool javascript_linkage;
};
struct ExternalBuiltinDeclaration : BuiltinDeclaration {
DEFINE_AST_NODE_LEAF_BOILERPLATE(ExternalBuiltinDeclaration)
ExternalBuiltinDeclaration(SourcePosition pos, bool javascript_linkage,
std::string name, ParameterList parameters,
ExternalBuiltinDeclaration(SourcePosition pos, bool transitioning,
bool javascript_linkage, std::string name,
ParameterList parameters,
TypeExpression* return_type)
: BuiltinDeclaration(kKind, pos, javascript_linkage, std::move(name),
std::move(parameters), return_type) {}
: BuiltinDeclaration(kKind, pos, javascript_linkage, transitioning,
std::move(name), std::move(parameters),
return_type) {}
};
struct TorqueBuiltinDeclaration : BuiltinDeclaration {
DEFINE_AST_NODE_LEAF_BOILERPLATE(TorqueBuiltinDeclaration)
TorqueBuiltinDeclaration(SourcePosition pos, bool javascript_linkage,
std::string name, ParameterList parameters,
TorqueBuiltinDeclaration(SourcePosition pos, bool transitioning,
bool javascript_linkage, std::string name,
ParameterList parameters,
TypeExpression* return_type)
: BuiltinDeclaration(kKind, pos, javascript_linkage, std::move(name),
std::move(parameters), return_type) {}
: BuiltinDeclaration(kKind, pos, javascript_linkage, transitioning,
std::move(name), std::move(parameters),
return_type) {}
};
struct ExternalRuntimeDeclaration : CallableNode {
DEFINE_AST_NODE_LEAF_BOILERPLATE(ExternalRuntimeDeclaration)
ExternalRuntimeDeclaration(SourcePosition pos, std::string name,
ParameterList parameters,
ExternalRuntimeDeclaration(SourcePosition pos, bool transitioning,
std::string name, ParameterList parameters,
TypeExpression* return_type)
: CallableNode(kKind, pos, name, parameters, return_type, {}) {}
: CallableNode(kKind, pos, transitioning, name, parameters, return_type,
{}) {}
};
struct ConstDeclaration : Declaration {
......
......@@ -13,38 +13,52 @@ namespace torque {
void Block::SetInputTypes(const Stack<const Type*>& input_types) {
if (!input_types_) {
input_types_ = input_types;
} else if (*input_types_ != input_types) {
std::stringstream error;
error << "incompatible types at branch:\n";
for (intptr_t i = std::max(input_types_->Size(), input_types.Size()) - 1;
i >= 0; --i) {
base::Optional<const Type*> left;
base::Optional<const Type*> right;
if (static_cast<size_t>(i) < input_types.Size()) {
left = input_types.Peek(BottomOffset{static_cast<size_t>(i)});
}
if (static_cast<size_t>(i) < input_types_->Size()) {
right = input_types_->Peek(BottomOffset{static_cast<size_t>(i)});
return;
} else if (*input_types_ == input_types) {
return;
}
Stack<const Type*> merged_types;
auto c2_iterator = input_types.begin();
for (const Type* c1 : *input_types_) {
const Type* merged_type = TypeOracle::GetUnionType(c1, *c2_iterator++);
merged_types.Push(merged_type);
}
if (merged_types.Size() == input_types_->Size()) {
input_types_ = merged_types;
return;
}
std::stringstream error;
error << "incompatible types at branch:\n";
for (intptr_t i = std::max(input_types_->Size(), input_types.Size()) - 1;
i >= 0; --i) {
base::Optional<const Type*> left;
base::Optional<const Type*> right;
if (static_cast<size_t>(i) < input_types.Size()) {
left = input_types.Peek(BottomOffset{static_cast<size_t>(i)});
}
if (static_cast<size_t>(i) < input_types_->Size()) {
right = input_types_->Peek(BottomOffset{static_cast<size_t>(i)});
}
if (left && right && *left == *right) {
error << **left << "\n";
} else {
if (left) {
error << **left;
} else {
error << "/*missing*/";
}
if (left && right && *left == *right) {
error << **left << "\n";
error << " => ";
if (right) {
error << **right;
} else {
if (left) {
error << **left;
} else {
error << "/*missing*/";
}
error << " => ";
if (right) {
error << **right;
} else {
error << "/*missing*/";
}
error << "\n";
error << "/*missing*/";
}
error << "\n";
}
ReportError(error.str());
}
ReportError(error.str());
}
void CfgAssembler::Bind(Block* block) {
......
......@@ -136,6 +136,8 @@ class CfgAssembler {
void Unreachable();
void DebugBreak();
void PrintCurrentStack(std::ostream& s) { s << "stack: " << current_stack_; }
private:
Stack<const Type*> current_stack_;
ControlFlowGraph cfg_;
......
......@@ -12,7 +12,11 @@ namespace internal {
namespace torque {
std::ostream& operator<<(std::ostream& os, const Callable& m) {
os << "callable " << m.name() << "(";
if (m.generic()) {
os << "callable " << (*m.generic())->name() << "(";
} else {
os << "callable " << m.name() << "(";
}
if (m.signature().implicit_count != 0) {
os << "implicit ";
TypeVector implicit_parameter_types(
......
......@@ -150,20 +150,24 @@ class Callable : public Declarable {
}
void IncrementReturns() { ++returns_; }
bool HasReturns() const { return returns_; }
bool IsTransitioning() const { return transitioning_; }
base::Optional<Generic*> generic() const { return generic_; }
protected:
Callable(Declarable::Kind kind, const std::string& name,
const Signature& signature, base::Optional<Generic*> generic)
const Signature& signature, bool transitioning,
base::Optional<Generic*> generic)
: Declarable(kind),
name_(name),
signature_(signature),
transitioning_(transitioning),
returns_(0),
generic_(generic) {}
private:
std::string name_;
Signature signature_;
bool transitioning_;
size_t returns_;
base::Optional<Generic*> generic_;
};
......@@ -174,9 +178,9 @@ class Macro : public Callable {
private:
friend class Declarations;
Macro(const std::string& name, const Signature& signature,
Macro(const std::string& name, const Signature& signature, bool transitioning,
base::Optional<Generic*> generic)
: Callable(Declarable::kMacro, name, signature, generic) {
: Callable(Declarable::kMacro, name, signature, transitioning, generic) {
if (signature.parameter_types.var_args) {
ReportError("Varargs are not supported for macros.");
}
......@@ -212,8 +216,9 @@ class Builtin : public Callable {
private:
friend class Declarations;
Builtin(const std::string& name, Builtin::Kind kind, bool external,
const Signature& signature, base::Optional<Generic*> generic)
: Callable(Declarable::kBuiltin, name, signature, generic),
const Signature& signature, bool transitioning,
base::Optional<Generic*> generic)
: Callable(Declarable::kBuiltin, name, signature, transitioning, generic),
kind_(kind),
external_(external) {}
......@@ -228,8 +233,9 @@ class RuntimeFunction : public Callable {
private:
friend class Declarations;
RuntimeFunction(const std::string& name, const Signature& signature,
base::Optional<Generic*> generic)
: Callable(Declarable::kRuntimeFunction, name, signature, generic) {}
bool transitioning, base::Optional<Generic*> generic)
: Callable(Declarable::kRuntimeFunction, name, signature, transitioning,
generic) {}
};
class Generic : public Declarable {
......
......@@ -107,7 +107,7 @@ Builtin* DeclarationVisitor::BuiltinDeclarationCommon(
std::string generated_name = GetGeneratedCallableName(
decl->name, declarations()->GetCurrentSpecializationTypeNamesVector());
return declarations()->DeclareBuiltin(generated_name, kind, external,
signature);
signature, decl->transitioning);
}
void DeclarationVisitor::Visit(ExternalRuntimeDeclaration* decl,
......@@ -135,7 +135,8 @@ void DeclarationVisitor::Visit(ExternalRuntimeDeclaration* decl,
ReportError(stream.str());
}
declarations()->DeclareRuntimeFunction(decl->name, signature);
declarations()->DeclareRuntimeFunction(decl->name, signature,
decl->transitioning);
}
void DeclarationVisitor::Visit(ExternalMacroDeclaration* decl,
......@@ -147,7 +148,8 @@ void DeclarationVisitor::Visit(ExternalMacroDeclaration* decl,
std::string generated_name = GetGeneratedCallableName(
decl->name, declarations()->GetCurrentSpecializationTypeNamesVector());
declarations()->DeclareMacro(generated_name, signature, decl->op);
declarations()->DeclareMacro(generated_name, signature, decl->transitioning,
decl->op);
}
void DeclarationVisitor::Visit(TorqueBuiltinDeclaration* decl,
......@@ -162,8 +164,8 @@ void DeclarationVisitor::Visit(TorqueMacroDeclaration* decl,
const Signature& signature, Statement* body) {
std::string generated_name = GetGeneratedCallableName(
decl->name, declarations()->GetCurrentSpecializationTypeNamesVector());
Macro* macro =
declarations()->DeclareMacro(generated_name, signature, decl->op);
Macro* macro = declarations()->DeclareMacro(generated_name, signature,
decl->transitioning, decl->op);
CurrentCallableActivator activator(global_context_, macro, decl);
......@@ -427,15 +429,19 @@ void DeclarationVisitor::Visit(CallExpression* expr) {
void DeclarationVisitor::Visit(TypeDeclaration* decl) {
std::string generates = decl->generates ? *decl->generates : std::string("");
const AbstractType* type = declarations()->DeclareAbstractType(
decl->name, generates, {}, decl->extends);
decl->name, decl->transient, generates, {}, decl->extends);
if (decl->constexpr_generates) {
if (decl->transient) {
ReportError("cannot declare a transient type that is also constexpr");
}
std::string constexpr_name = CONSTEXPR_TYPE_PREFIX + decl->name;
base::Optional<std::string> constexpr_extends;
if (decl->extends)
constexpr_extends = CONSTEXPR_TYPE_PREFIX + *decl->extends;
declarations()->DeclareAbstractType(
constexpr_name, *decl->constexpr_generates, type, constexpr_extends);
declarations()->DeclareAbstractType(constexpr_name, false,
*decl->constexpr_generates, type,
constexpr_extends);
}
}
......
......@@ -186,7 +186,7 @@ ModuleConstant* Declarations::LookupModuleConstant(const std::string& name) {
}
const AbstractType* Declarations::DeclareAbstractType(
const std::string& name, const std::string& generated,
const std::string& name, bool transient, const std::string& generated,
base::Optional<const AbstractType*> non_constexpr_version,
const base::Optional<std::string>& parent) {
CheckAlreadyDeclared(name, "type");
......@@ -207,7 +207,7 @@ const AbstractType* Declarations::DeclareAbstractType(
parent_type = TypeAlias::cast(maybe_parent_type)->type();
}
const AbstractType* type = TypeOracle::GetAbstractType(
parent_type, name, generated, non_constexpr_version);
parent_type, name, transient, generated, non_constexpr_version);
DeclareType(name, type);
return type;
}
......@@ -255,9 +255,10 @@ MacroList* Declarations::GetMacroListForName(const std::string& name,
Macro* Declarations::DeclareMacro(const std::string& name,
const Signature& signature,
bool transitioning,
base::Optional<std::string> op) {
Macro* macro = RegisterDeclarable(
std::unique_ptr<Macro>(new Macro(name, signature, GetCurrentGeneric())));
Macro* macro = RegisterDeclarable(std::unique_ptr<Macro>(
new Macro(name, signature, transitioning, GetCurrentGeneric())));
GetMacroListForName(name, signature)->AddMacro(macro);
if (op) GetMacroListForName(*op, signature)->AddMacro(macro);
return macro;
......@@ -265,19 +266,20 @@ Macro* Declarations::DeclareMacro(const std::string& name,
Builtin* Declarations::DeclareBuiltin(const std::string& name,
Builtin::Kind kind, bool external,
const Signature& signature) {
const Signature& signature,
bool transitioning) {
CheckAlreadyDeclared(name, "builtin");
Builtin* result =
new Builtin(name, kind, external, signature, GetCurrentGeneric());
Builtin* result = new Builtin(name, kind, external, signature, transitioning,
GetCurrentGeneric());
Declare(name, std::unique_ptr<Declarable>(result));
return result;
}
RuntimeFunction* Declarations::DeclareRuntimeFunction(
const std::string& name, const Signature& signature) {
const std::string& name, const Signature& signature, bool transitioning) {
CheckAlreadyDeclared(name, "runtime function");
RuntimeFunction* result =
new RuntimeFunction(name, signature, GetCurrentGeneric());
new RuntimeFunction(name, signature, transitioning, GetCurrentGeneric());
Declare(name, std::unique_ptr<Declarable>(result));
return result;
}
......
......@@ -64,7 +64,7 @@ class Declarations {
ModuleConstant* LookupModuleConstant(const std::string& name);
const AbstractType* DeclareAbstractType(
const std::string& name, const std::string& generated,
const std::string& name, bool transient, const std::string& generated,
base::Optional<const AbstractType*> non_constexpr_version,
const base::Optional<std::string>& parent = {});
......@@ -74,13 +74,15 @@ class Declarations {
const std::vector<NameAndType>& fields);
Macro* DeclareMacro(const std::string& name, const Signature& signature,
base::Optional<std::string> op = {});
bool transitioning, base::Optional<std::string> op = {});
Builtin* DeclareBuiltin(const std::string& name, Builtin::Kind kind,
bool external, const Signature& signature);
bool external, const Signature& signature,
bool transitioning);
RuntimeFunction* DeclareRuntimeFunction(const std::string& name,
const Signature& signature);
const Signature& signature,
bool transitioning);
void DeclareExternConstant(const std::string& name, const Type* type,
std::string value);
......
......@@ -489,7 +489,11 @@ const Type* ImplementationVisitor::Visit(
}
TypeVector lowered_types = LowerType(*type);
for (const Type* type : lowered_types) {
assembler().Emit(PushUninitializedInstruction{type});
assembler().Emit(PushUninitializedInstruction{TypeOracle::GetTopType(
"unitialized variable '" + stmt->name + "' of type " +
type->ToString() + " originally defined at " +
PositionAsString(stmt->pos),
type)});
}
init_result =
VisitResult(*type, assembler().TopRange(lowered_types.size()));
......@@ -1759,6 +1763,16 @@ VisitResult ImplementationVisitor::GenerateCall(
ReportError(s.str());
}
if (callable->IsTransitioning()) {
if (!global_context_.GetCurrentCallable()->IsTransitioning()) {
std::stringstream s;
s << *global_context_.GetCurrentCallable()
<< " isn't marked transitioning but calls the transitioning "
<< *callable;
ReportError(s.str());
}
}
if (auto* builtin = Builtin::DynamicCast(callable)) {
assembler().Emit(
CallBuiltinInstruction{is_tailcall, builtin, argument_range.Size()});
......
......@@ -25,8 +25,12 @@ void PeekInstruction::TypeInstruction(Stack<const Type*>* stack,
ControlFlowGraph* cfg) const {
const Type* type = stack->Peek(slot);
if (widened_type) {
if (type->IsTopType()) {
const TopType* top_type = TopType::cast(type);
ReportError("use of " + top_type->reason());
}
if (!type->IsSubtypeOf(*widened_type)) {
ReportError("type ", type, " is not a subtype of ", *widened_type);
ReportError("type ", *type, " is not a subtype of ", **widened_type);
}
type = *widened_type;
}
......@@ -66,6 +70,21 @@ void ModuleConstantInstruction::TypeInstruction(Stack<const Type*>* stack,
stack->PushMany(LowerType(constant->type()));
}
void InstructionBase::InvalidateTransientTypes(
Stack<const Type*>* stack) const {
auto current = stack->begin();
while (current != stack->end()) {
if ((*current)->IsTransient()) {
std::stringstream stream;
stream << "type " << **current
<< " is made invalid by transitioning callable invocation at "
<< PositionAsString(pos);
*current = TypeOracle::GetTopType(stream.str(), *current);
}
++current;
}
}
void CallCsaMacroInstruction::TypeInstruction(Stack<const Type*>* stack,
ControlFlowGraph* cfg) const {
std::vector<const Type*> parameter_types =
......@@ -81,6 +100,10 @@ void CallCsaMacroInstruction::TypeInstruction(Stack<const Type*>* stack,
}
if (!parameter_types.empty()) ReportError("missing arguments");
if (macro->IsTransitioning()) {
InvalidateTransientTypes(stack);
}
stack->PushMany(LowerType(macro->signature().return_type));
}
......@@ -109,6 +132,10 @@ void CallCsaMacroAndBranchInstruction::TypeInstruction(
label_blocks[i]->SetInputTypes(std::move(continuation_stack));
}
if (macro->IsTransitioning()) {
InvalidateTransientTypes(stack);
}
if (macro->signature().return_type != TypeOracle::GetNeverType()) {
Stack<const Type*> return_stack = *stack;
return_stack.PushMany(LowerType(macro->signature().return_type));
......@@ -130,6 +157,9 @@ void CallBuiltinInstruction::TypeInstruction(Stack<const Type*>* stack,
LowerParameterTypes(builtin->signature().parameter_types)) {
ReportError("wrong argument types");
}
if (builtin->IsTransitioning()) {
InvalidateTransientTypes(stack);
}
stack->PushMany(LowerType(builtin->signature().return_type));
}
......@@ -141,6 +171,9 @@ void CallBuiltinPointerInstruction::TypeInstruction(
if (argument_types != LowerParameterTypes(f->parameter_types())) {
ReportError("wrong argument types");
}
if (example_builtin->IsTransitioning()) {
InvalidateTransientTypes(stack);
}
stack->PushMany(LowerType(f->return_type()));
}
......@@ -152,6 +185,9 @@ void CallRuntimeInstruction::TypeInstruction(Stack<const Type*>* stack,
argc)) {
ReportError("wrong argument types");
}
if (runtime_function->IsTransitioning()) {
InvalidateTransientTypes(stack);
}
const Type* return_type = runtime_function->signature().return_type;
if (return_type != TypeOracle::GetNeverType()) {
stack->PushMany(LowerType(return_type));
......
......@@ -65,6 +65,7 @@ struct InstructionBase {
virtual void TypeInstruction(Stack<const Type*>* stack,
ControlFlowGraph* cfg) const = 0;
void InvalidateTransientTypes(Stack<const Type*>* stack) const;
virtual bool IsBlockTerminator() const { return false; }
virtual void AppendSuccessorBlocks(std::vector<Block*>* block_list) const {}
......
......@@ -346,6 +346,7 @@ base::Optional<ParseResult> MakeVoidType(ParseResultIterator* child_results) {
base::Optional<ParseResult> MakeExternalMacro(
ParseResultIterator* child_results) {
auto transitioning = child_results->NextAs<bool>();
auto operator_name = child_results->NextAs<base::Optional<std::string>>();
auto name = child_results->NextAs<std::string>();
auto generic_parameters = child_results->NextAs<GenericParameters>();
......@@ -355,7 +356,7 @@ base::Optional<ParseResult> MakeExternalMacro(
auto return_type = child_results->NextAs<TypeExpression*>();
auto labels = child_results->NextAs<LabelAndTypesVector>();
MacroDeclaration* macro = MakeNode<ExternalMacroDeclaration>(
name, operator_name, args, return_type, labels);
transitioning, name, operator_name, args, return_type, labels);
Declaration* result;
if (generic_parameters.empty()) {
result = MakeNode<StandardDeclaration>(macro, nullptr);
......@@ -367,6 +368,7 @@ base::Optional<ParseResult> MakeExternalMacro(
base::Optional<ParseResult> MakeTorqueMacroDeclaration(
ParseResultIterator* child_results) {
auto transitioning = child_results->NextAs<bool>();
auto operator_name = child_results->NextAs<base::Optional<std::string>>();
auto name = child_results->NextAs<std::string>();
if (!IsUpperCamelCase(name)) {
......@@ -381,7 +383,7 @@ base::Optional<ParseResult> MakeTorqueMacroDeclaration(
auto labels = child_results->NextAs<LabelAndTypesVector>();
auto body = child_results->NextAs<base::Optional<Statement*>>();
MacroDeclaration* macro = MakeNode<TorqueMacroDeclaration>(
name, operator_name, args, return_type, labels);
transitioning, name, operator_name, args, return_type, labels);
Declaration* result;
if (generic_parameters.empty()) {
if (!body) ReportError("A non-generic declaration needs a body.");
......@@ -394,6 +396,7 @@ base::Optional<ParseResult> MakeTorqueMacroDeclaration(
base::Optional<ParseResult> MakeTorqueBuiltinDeclaration(
ParseResultIterator* child_results) {
auto transitioning = child_results->NextAs<bool>();
auto javascript_linkage = child_results->NextAs<bool>();
auto name = child_results->NextAs<std::string>();
if (!IsUpperCamelCase(name)) {
......@@ -407,7 +410,7 @@ base::Optional<ParseResult> MakeTorqueBuiltinDeclaration(
auto return_type = child_results->NextAs<TypeExpression*>();
auto body = child_results->NextAs<base::Optional<Statement*>>();
BuiltinDeclaration* builtin = MakeNode<TorqueBuiltinDeclaration>(
javascript_linkage, name, args, return_type);
transitioning, javascript_linkage, name, args, return_type);
Declaration* result;
if (generic_parameters.empty()) {
if (!body) ReportError("A non-generic declaration needs a body.");
......@@ -452,6 +455,7 @@ base::Optional<ParseResult> MakeTypeAliasDeclaration(
base::Optional<ParseResult> MakeTypeDeclaration(
ParseResultIterator* child_results) {
auto transient = child_results->NextAs<bool>();
auto name = child_results->NextAs<std::string>();
if (!IsValidTypeName(name)) {
NamingConventionError("Type", name, "UpperCamelCase");
......@@ -461,7 +465,7 @@ base::Optional<ParseResult> MakeTypeDeclaration(
auto constexpr_generates =
child_results->NextAs<base::Optional<std::string>>();
Declaration* result = MakeNode<TypeDeclaration>(
std::move(name), std::move(extends), std::move(generates),
std::move(name), transient, std::move(extends), std::move(generates),
std::move(constexpr_generates));
return ParseResult{result};
}
......@@ -505,6 +509,7 @@ base::Optional<ParseResult> MakeStructDeclaration(
base::Optional<ParseResult> MakeExternalBuiltin(
ParseResultIterator* child_results) {
auto transitioning = child_results->NextAs<bool>();
auto js_linkage = child_results->NextAs<bool>();
auto name = child_results->NextAs<std::string>();
auto generic_parameters = child_results->NextAs<GenericParameters>();
......@@ -512,8 +517,8 @@ base::Optional<ParseResult> MakeExternalBuiltin(
auto args = child_results->NextAs<ParameterList>();
auto return_type = child_results->NextAs<TypeExpression*>();
BuiltinDeclaration* builtin =
MakeNode<ExternalBuiltinDeclaration>(js_linkage, name, args, return_type);
BuiltinDeclaration* builtin = MakeNode<ExternalBuiltinDeclaration>(
transitioning, js_linkage, name, args, return_type);
Declaration* result;
if (generic_parameters.empty()) {
result = MakeNode<StandardDeclaration>(builtin, nullptr);
......@@ -525,11 +530,12 @@ base::Optional<ParseResult> MakeExternalBuiltin(
base::Optional<ParseResult> MakeExternalRuntime(
ParseResultIterator* child_results) {
auto transitioning = child_results->NextAs<bool>();
auto name = child_results->NextAs<std::string>();
auto args = child_results->NextAs<ParameterList>();
auto return_type = child_results->NextAs<TypeExpression*>();
ExternalRuntimeDeclaration* runtime =
MakeNode<ExternalRuntimeDeclaration>(name, args, return_type);
ExternalRuntimeDeclaration* runtime = MakeNode<ExternalRuntimeDeclaration>(
transitioning, name, args, return_type);
Declaration* result = MakeNode<StandardDeclaration>(runtime, nullptr);
return ParseResult{result};
}
......@@ -1359,7 +1365,7 @@ struct TorqueGrammar : Grammar {
Rule({Token("const"), &identifier, Token(":"), &type, Token("generates"),
&externalString, Token(";")},
MakeExternConstDeclaration),
Rule({Token("type"), &identifier,
Rule({CheckIf(Token("transient")), Token("type"), &identifier,
Optional<std::string>(Sequence({Token("extends"), &identifier})),
Optional<std::string>(
Sequence({Token("generates"), &externalString})),
......@@ -1369,7 +1375,7 @@ struct TorqueGrammar : Grammar {
MakeTypeDeclaration),
Rule({Token("type"), &identifier, Token("="), &type, Token(";")},
MakeTypeAliasDeclaration),
Rule({Token("extern"),
Rule({Token("extern"), CheckIf(Token("transitioning")),
Optional<std::string>(
Sequence({Token("operator"), &externalString})),
Token("macro"), &identifier,
......@@ -1377,21 +1383,25 @@ struct TorqueGrammar : Grammar {
&typeListMaybeVarArgs, &optionalReturnType, optionalLabelList,
Token(";")},
MakeExternalMacro),
Rule({Token("extern"), CheckIf(Token("javascript")), Token("builtin"),
&identifier, TryOrDefault<GenericParameters>(&genericParameters),
Rule({Token("extern"), CheckIf(Token("transitioning")),
CheckIf(Token("javascript")), Token("builtin"), &identifier,
TryOrDefault<GenericParameters>(&genericParameters),
&typeListMaybeVarArgs, &optionalReturnType, Token(";")},
MakeExternalBuiltin),
Rule({Token("extern"), Token("runtime"), &identifier,
&typeListMaybeVarArgs, &optionalReturnType, Token(";")},
MakeExternalRuntime),
Rule({Optional<std::string>(
Rule(
{Token("extern"), CheckIf(Token("transitioning")), Token("runtime"),
&identifier, &typeListMaybeVarArgs, &optionalReturnType, Token(";")},
MakeExternalRuntime),
Rule({CheckIf(Token("transitioning")),
Optional<std::string>(
Sequence({Token("operator"), &externalString})),
Token("macro"), &identifier,
TryOrDefault<GenericParameters>(&genericParameters),
&parameterListNoVararg, &optionalReturnType, optionalLabelList,
&optionalBody},
MakeTorqueMacroDeclaration),
Rule({CheckIf(Token("javascript")), Token("builtin"), &identifier,
Rule({CheckIf(Token("transitioning")), CheckIf(Token("javascript")),
Token("builtin"), &identifier,
TryOrDefault<GenericParameters>(&genericParameters),
&parameterListAllowVararg, &optionalReturnType, &optionalBody},
MakeTorqueBuiltinDeclaration),
......
......@@ -21,10 +21,12 @@ class TypeOracle : public ContextualClass<TypeOracle> {
: declarations_(declarations) {}
static const AbstractType* GetAbstractType(
const Type* parent, std::string name, std::string generated,
const Type* parent, std::string name, bool transient,
std::string generated,
base::Optional<const AbstractType*> non_constexpr_version) {
AbstractType* result = new AbstractType(
parent, std::move(name), std::move(generated), non_constexpr_version);
AbstractType* result =
new AbstractType(parent, transient, std::move(name),
std::move(generated), non_constexpr_version);
Get().nominal_types_.push_back(std::unique_ptr<AbstractType>(result));
return result;
}
......@@ -59,6 +61,13 @@ class TypeOracle : public ContextualClass<TypeOracle> {
return GetUnionType(std::move(result));
}
static const TopType* GetTopType(std::string reason,
const Type* source_type) {
TopType* result = new TopType(std::move(reason), source_type);
Get().top_types_.push_back(std::unique_ptr<TopType>(result));
return result;
}
static const Type* GetArgumentsType() {
return Get().GetBuiltinType(ARGUMENTS_TYPE_STRING);
}
......@@ -110,6 +119,7 @@ class TypeOracle : public ContextualClass<TypeOracle> {
Deduplicator<UnionType> union_types_;
std::vector<std::unique_ptr<Type>> nominal_types_;
std::vector<std::unique_ptr<Type>> struct_types_;
std::vector<std::unique_ptr<Type>> top_types_;
};
} // namespace torque
......
......@@ -32,6 +32,7 @@ std::string Type::ToString() const {
}
bool Type::IsSubtypeOf(const Type* supertype) const {
if (supertype->IsTopType()) return true;
if (IsNever()) return true;
if (const UnionType* union_type = UnionType::DynamicCast(supertype)) {
return union_type->IsSupertypeOf(this);
......
......@@ -6,6 +6,7 @@
#define V8_TORQUE_TYPES_H_
#include <algorithm>
#include <map>
#include <set>
#include <string>
#include <vector>
......@@ -38,12 +39,14 @@ class Module;
class TypeBase {
public:
enum class Kind {
kTopType,
kAbstractType,
kFunctionPointerType,
kUnionType,
kStructType
};
virtual ~TypeBase() = default;
bool IsTopType() const { return kind() == Kind::kTopType; }
bool IsAbstractType() const { return kind() == Kind::kAbstractType; }
bool IsFunctionPointerType() const {
return kind() == Kind::kFunctionPointerType;
......@@ -95,6 +98,7 @@ class Type : public TypeBase {
virtual std::string GetGeneratedTypeName() const = 0;
virtual std::string GetGeneratedTNodeTypeName() const = 0;
virtual bool IsConstexpr() const = 0;
virtual bool IsTransient() const { return false; }
virtual const Type* NonConstexprVersion() const = 0;
static const Type* CommonSupertype(const Type* a, const Type* b);
void AddAlias(std::string alias) const { aliases_.insert(std::move(alias)); }
......@@ -124,6 +128,35 @@ struct NameAndType {
std::ostream& operator<<(std::ostream& os, const NameAndType& name_and_type);
class TopType final : public Type {
public:
DECLARE_TYPE_BOILERPLATE(TopType);
virtual std::string MangledName() const { return "top"; }
virtual std::string GetGeneratedTypeName() const { UNREACHABLE(); }
virtual std::string GetGeneratedTNodeTypeName() const {
return source_type_->GetGeneratedTNodeTypeName();
}
virtual bool IsConstexpr() const { return false; }
virtual const Type* NonConstexprVersion() const { return nullptr; }
virtual std::string ToExplicitString() const {
std::stringstream s;
s << "inaccessible " + source_type_->ToString();
return s.str();
}
const Type* source_type() const { return source_type_; }
const std::string reason() const { return reason_; }
private:
friend class TypeOracle;
explicit TopType(std::string reason, const Type* source_type)
: Type(Kind::kTopType, nullptr),
reason_(std::move(reason)),
source_type_(source_type) {}
std::string reason_;
const Type* source_type_;
};
class AbstractType final : public Type {
public:
DECLARE_TYPE_BOILERPLATE(AbstractType);
......@@ -143,10 +176,11 @@ class AbstractType final : public Type {
private:
friend class TypeOracle;
AbstractType(const Type* parent, const std::string& name,
AbstractType(const Type* parent, bool transient, const std::string& name,
const std::string& generated_type,
base::Optional<const AbstractType*> non_constexpr_version)
: Type(Kind::kAbstractType, parent),
transient_(transient),
name_(name),
generated_type_(generated_type),
non_constexpr_version_(non_constexpr_version) {
......@@ -154,6 +188,9 @@ class AbstractType final : public Type {
if (parent) DCHECK(parent->IsConstexpr() == IsConstexpr());
}
bool IsTransient() const override { return transient_; }
bool transient_;
const std::string name_;
const std::string generated_type_;
base::Optional<const AbstractType*> non_constexpr_version_;
......@@ -263,6 +300,15 @@ class UnionType final : public Type {
return false;
}
bool IsTransient() const override {
for (const Type* member : types_) {
if (member->IsTransient()) {
return true;
}
}
return false;
}
void Extend(const Type* t) {
if (const UnionType* union_type = UnionType::DynamicCast(t)) {
for (const Type* member : union_type->types_) {
......
......@@ -243,6 +243,13 @@ T* CheckNotNull(T* x) {
return x;
}
template <class T>
inline std::ostream& operator<<(std::ostream& os, Stack<T>& t) {
os << "Stack{";
PrintCommaSeparatedList(os, t);
os << "}";
return os;
}
class ToString {
public:
template <class T>
......
......@@ -124,7 +124,7 @@ module array {
// copied values from the prototype chain to the receiver if they were visible
// through a hole.
builtin Load<ElementsAccessor: type>(
transitioning builtin Load<ElementsAccessor: type>(
context: Context, sortState: FixedArray, elements: HeapObject,
index: Smi): Object {
return GetProperty(elements, index);
......@@ -193,7 +193,7 @@ module array {
return elems[index];
}
builtin Store<ElementsAccessor: type>(
transitioning builtin Store<ElementsAccessor: type>(
context: Context, sortState: FixedArray, elements: HeapObject, index: Smi,
value: Object): Smi {
SetProperty(elements, index, value);
......@@ -306,7 +306,7 @@ module array {
return 0;
}
builtin SortCompareUserFn(
transitioning builtin SortCompareUserFn(
context: Context, comparefn: Object, x: Object, y: Object): Number {
assert(comparefn != Undefined);
const cmpfn: Callable = UnsafeCast<Callable>(comparefn);
......@@ -499,7 +499,7 @@ module array {
EnsureSuccess(sortState) otherwise Bailout;
}
macro CallCopyFromTempArray(
transitioning macro CallCopyFromTempArray(
context: Context, sortState: FixedArray, dstElements: HeapObject,
dstPos: Smi, tempArray: FixedArray, srcPos: Smi, length: Smi)
labels Bailout {
......@@ -508,7 +508,7 @@ module array {
EnsureSuccess(sortState) otherwise Bailout;
}
macro CallCopyWithinSortArray(
transitioning macro CallCopyWithinSortArray(
context: Context, sortState: FixedArray, elements: HeapObject,
srcPos: Smi, dstPos: Smi, length: Smi)
labels Bailout {
......@@ -536,20 +536,20 @@ module array {
return result;
}
macro CallMergeAt(context: Context, sortState: FixedArray, i: Smi)
transitioning macro CallMergeAt(context: Context, sortState: FixedArray, i: Smi)
labels Bailout {
MergeAt(context, sortState, i);
EnsureSuccess(sortState) otherwise Bailout;
}
// Used for OOB asserts in Copy* builtins.
macro GetReceiverLengthProperty(implicit context: Context)(
transitioning macro GetReceiverLengthProperty(implicit context: Context)(
sortState: FixedArray): Smi {
return Cast<Smi>(GetLengthProperty(GetReceiver(sortState)))
otherwise unreachable;
}
macro CopyToTempArray(
transitioning macro CopyToTempArray(
context: Context, sortState: FixedArray, load: LoadFn,
srcElements: HeapObject, srcPos: Smi, tempArray: FixedArray, dstPos: Smi,
length: Smi)
......@@ -571,7 +571,7 @@ module array {
}
}
builtin CopyFromTempArray(
transitioning builtin CopyFromTempArray(
context: Context, sortState: FixedArray, dstElements: HeapObject,
dstPos: Smi, tempArray: FixedArray, srcPos: Smi, length: Smi): Smi {
assert(srcPos >= 0);
......@@ -598,7 +598,7 @@ module array {
}
}
builtin CopyWithinSortArray(
transitioning builtin CopyWithinSortArray(
context: Context, sortState: FixedArray, elements: HeapObject,
srcPos: Smi, dstPos: Smi, length: Smi): Smi {
assert(srcPos >= 0);
......@@ -806,7 +806,8 @@ module array {
// Merges the two runs at stack indices i and i + 1.
// Returns kFailure if we need to bailout, kSuccess otherwise.
builtin MergeAt(context: Context, sortState: FixedArray, i: Smi): Smi {
transitioning builtin MergeAt(
context: Context, sortState: FixedArray, i: Smi): Smi {
const stackSize: Smi = GetPendingRunsSize(sortState);
// We are only allowed to either merge the two top-most runs, or leave
......@@ -1159,7 +1160,7 @@ module array {
// array[baseB] < array[baseA],
// that array[baseA + lengthA - 1] belongs at the end of the merge,
// and should have lengthA <= lengthB.
macro MergeLow(
transitioning macro MergeLow(
context: Context, sortState: FixedArray, baseA: Smi, lengthAArg: Smi,
baseB: Smi, lengthBArg: Smi)
labels Bailout {
......@@ -1334,7 +1335,7 @@ module array {
// starting at baseB in a stable way, in-place. lengthA and lengthB must
// be > 0. Must also have that array[baseA + lengthA - 1] belongs at the
// end of the merge and should have lengthA >= lengthB.
macro MergeHigh(
transitioning macro MergeHigh(
context: Context, sortState: FixedArray, baseA: Smi, lengthAArg: Smi,
baseB: Smi, lengthBArg: Smi)
labels Bailout {
......@@ -1556,7 +1557,7 @@ module array {
// TODO(szuend): Remove unnecessary loads. This macro was refactored to
// improve readability, introducing unnecessary loads in the
// process. Determine if all these extra loads are ok.
macro MergeCollapse(context: Context, sortState: FixedArray)
transitioning macro MergeCollapse(context: Context, sortState: FixedArray)
labels Bailout {
const pendingRuns: FixedArray =
UnsafeCast<FixedArray>(sortState[kPendingRunsIdx]);
......@@ -1585,7 +1586,7 @@ module array {
// Regardless of invariants, merge all runs on the stack until only one
// remains. This is used at the end of the mergesort.
macro MergeForceCollapse(context: Context, sortState: FixedArray)
transitioning macro MergeForceCollapse(context: Context, sortState: FixedArray)
labels Bailout {
let pendingRuns: FixedArray =
UnsafeCast<FixedArray>(sortState[kPendingRunsIdx]);
......@@ -1628,7 +1629,8 @@ module array {
CanUseSameAccessor<GenericElementsAccessor>;
}
macro ArrayTimSortImpl(context: Context, sortState: FixedArray, length: Smi)
transitioning macro ArrayTimSortImpl(
context: Context, sortState: FixedArray, length: Smi)
labels Bailout {
InitializeSortState(sortState);
......@@ -1671,7 +1673,7 @@ module array {
UnsafeCast<FixedArray>(sortState[kPendingRunsIdx]), 0) == length);
}
builtin ArrayTimSort(
transitioning builtin ArrayTimSort(
context: Context, sortState: FixedArray, length: Smi): Object {
try {
ArrayTimSortImpl(context, sortState, length)
......@@ -1705,7 +1707,7 @@ module array {
extern runtime PrepareElementsForSort(Context, Object, Number): Smi;
// https://tc39.github.io/ecma262/#sec-array.prototype.sort
javascript builtin ArrayPrototypeSort(
transitioning javascript builtin ArrayPrototypeSort(
context: Context, receiver: Object, ...arguments): Object {
// 1. If comparefn is not undefined and IsCallable(comparefn) is false,
// throw a TypeError exception.
......
......@@ -30,7 +30,7 @@ syn keyword torqueFunction macro builtin runtime
syn keyword torqueKeyword cast convert from_constexpr min max unsafe_cast
syn keyword torqueLabel case
syn keyword torqueMatching try label
syn keyword torqueModifier extern javascript constexpr
syn keyword torqueModifier extern javascript constexpr transitioning transient
syn match torqueNumber /\v<[0-9]+(\.[0-9]*)?>/
syn match torqueNumber /\v<0x[0-9a-fA-F]+>/
syn keyword torqueOperator operator
......
......@@ -65,7 +65,7 @@
},
{
"name": "keyword.other.torque",
"match": "\\b(constexpr|module|macro|builtin|runtime|javascript|implicit|deferred|label|labels|tail|let|generates|type|extends|extern|const|typeswitch|case)\\b"
"match": "\\b(constexpr|module|macro|builtin|runtime|javascript|implicit|deferred|label|labels|tail|let|generates|type|extends|extern|const|typeswitch|case|transient|transitioning)\\b"
},
{
"name": "keyword.operator.torque",
......
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