summaryrefslogtreecommitdiff
path: root/chromium/v8/src/builtins
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@qt.io>2020-10-12 14:27:29 +0200
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2020-10-13 09:35:20 +0000
commitc30a6232df03e1efbd9f3b226777b07e087a1122 (patch)
treee992f45784689f373bcc38d1b79a239ebe17ee23 /chromium/v8/src/builtins
parent7b5b123ac58f58ffde0f4f6e488bcd09aa4decd3 (diff)
downloadqtwebengine-chromium-85-based.tar.gz
BASELINE: Update Chromium to 85.0.4183.14085-based
Change-Id: Iaa42f4680837c57725b1344f108c0196741f6057 Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
Diffstat (limited to 'chromium/v8/src/builtins')
-rw-r--r--chromium/v8/src/builtins/aggregate-error.tq49
-rw-r--r--chromium/v8/src/builtins/array-join.tq4
-rw-r--r--chromium/v8/src/builtins/array-slice.tq12
-rw-r--r--chromium/v8/src/builtins/base.tq132
-rw-r--r--chromium/v8/src/builtins/bigint.tq1
-rw-r--r--chromium/v8/src/builtins/builtins-array-gen.cc44
-rw-r--r--chromium/v8/src/builtins/builtins-array-gen.h12
-rw-r--r--chromium/v8/src/builtins/builtins-async-iterator-gen.cc94
-rw-r--r--chromium/v8/src/builtins/builtins-call-gen.cc73
-rw-r--r--chromium/v8/src/builtins/builtins-collections-gen.cc2
-rw-r--r--chromium/v8/src/builtins/builtins-constructor-gen.cc79
-rw-r--r--chromium/v8/src/builtins/builtins-conversion-gen.cc386
-rw-r--r--chromium/v8/src/builtins/builtins-date-gen.cc2
-rw-r--r--chromium/v8/src/builtins/builtins-definitions.h115
-rw-r--r--chromium/v8/src/builtins/builtins-descriptors.h28
-rw-r--r--chromium/v8/src/builtins/builtins-function-gen.cc202
-rw-r--r--chromium/v8/src/builtins/builtins-handler-gen.cc39
-rw-r--r--chromium/v8/src/builtins/builtins-internal-gen.cc20
-rw-r--r--chromium/v8/src/builtins/builtins-microtask-queue-gen.cc7
-rw-r--r--chromium/v8/src/builtins/builtins-number-gen.cc1060
-rw-r--r--chromium/v8/src/builtins/builtins-object-gen.cc7
-rw-r--r--chromium/v8/src/builtins/builtins-promise.h4
-rw-r--r--chromium/v8/src/builtins/builtins-regexp-gen.cc10
-rw-r--r--chromium/v8/src/builtins/builtins-string-gen.cc16
-rw-r--r--chromium/v8/src/builtins/builtins-string.cc12
-rw-r--r--chromium/v8/src/builtins/builtins-string.tq37
-rw-r--r--chromium/v8/src/builtins/builtins-typed-array-gen.cc44
-rw-r--r--chromium/v8/src/builtins/builtins-typed-array-gen.h5
-rw-r--r--chromium/v8/src/builtins/builtins-wasm-gen.cc153
-rw-r--r--chromium/v8/src/builtins/builtins-wasm-gen.h4
-rw-r--r--chromium/v8/src/builtins/cast.tq313
-rw-r--r--chromium/v8/src/builtins/constants-table-builder.cc37
-rw-r--r--chromium/v8/src/builtins/constants-table-builder.h5
-rw-r--r--chromium/v8/src/builtins/conversion.tq232
-rw-r--r--chromium/v8/src/builtins/convert.tq15
-rw-r--r--chromium/v8/src/builtins/function.tq109
-rw-r--r--chromium/v8/src/builtins/growable-fixed-array.tq3
-rw-r--r--chromium/v8/src/builtins/internal.tq35
-rw-r--r--chromium/v8/src/builtins/math.tq6
-rw-r--r--chromium/v8/src/builtins/number.tq678
-rw-r--r--chromium/v8/src/builtins/promise-abstract-operations.tq45
-rw-r--r--chromium/v8/src/builtins/promise-all-element-closure.tq99
-rw-r--r--chromium/v8/src/builtins/promise-all.tq301
-rw-r--r--chromium/v8/src/builtins/promise-any.tq130
-rw-r--r--chromium/v8/src/builtins/promise-race.tq56
-rw-r--r--chromium/v8/src/builtins/regexp.tq3
-rw-r--r--chromium/v8/src/builtins/setup-builtins-internal.cc5
-rw-r--r--chromium/v8/src/builtins/torque-internal.tq28
-rw-r--r--chromium/v8/src/builtins/typed-array-entries.tq27
-rw-r--r--chromium/v8/src/builtins/typed-array-keys.tq27
-rw-r--r--chromium/v8/src/builtins/typed-array-values.tq27
-rw-r--r--chromium/v8/src/builtins/wasm.tq129
52 files changed, 2276 insertions, 2687 deletions
diff --git a/chromium/v8/src/builtins/aggregate-error.tq b/chromium/v8/src/builtins/aggregate-error.tq
new file mode 100644
index 00000000000..0f4a47b3e73
--- /dev/null
+++ b/chromium/v8/src/builtins/aggregate-error.tq
@@ -0,0 +1,49 @@
+// Copyright 2020 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include 'src/objects/js-objects.h'
+
+namespace error {
+
+transitioning javascript builtin AggregateErrorConstructor(
+ js-implicit context: NativeContext, target: JSFunction,
+ newTarget: JSAny)(...arguments): JSAny {
+ // This function is implementing the spec as suggested by
+ // https://github.com/tc39/proposal-promise-any/pull/59 . FIXME(marja):
+ // change this if the PR is declined, otherwise remove the comment.
+
+ // 1. If NewTarget is undefined, let newTarget be the active function
+ // object, else let newTarget be NewTarget.
+ // 2. Let O be ? OrdinaryCreateFromConstructor(newTarget,
+ // "%AggregateError.prototype%", « [[ErrorData]], [[AggregateErrors]] »).
+ // 3. If _message_ is not _undefined_, then
+ // a. Let msg be ? ToString(_message_).
+ // b. Let msgDesc be the PropertyDescriptor { [[Value]]: _msg_,
+ // [[Writable]]: *true*, [[Enumerable]]: *false*, [[Configurable]]: *true*
+ // c. Perform ! DefinePropertyOrThrow(_O_, *"message"*, _msgDesc_).
+ const message: JSAny = arguments[1];
+ const obj: JSObject =
+ ConstructAggregateErrorHelper(context, target, newTarget, message);
+
+ // 4. Let errorsList be ? IterableToList(errors).
+ const errors: JSAny = arguments[0];
+ const errorsList = iterator::IterableToListWithSymbolLookup(errors);
+
+ // 5. Perform ! DefinePropertyOrThrow(_O_, `"errors"`, Property Descriptor {
+ // [[Configurable]]: *true*, [[Enumerable]]: *false*, [[Writable]]: *true*,
+ // [[Value]]: ! CreateArrayFromList(_errorsList_) }).
+ SetOwnPropertyIgnoreAttributes(
+ obj, ErrorsStringConstant(), errorsList,
+ SmiConstant(PropertyAttributes::DONT_ENUM));
+
+ // 6. Return O.
+ return obj;
+}
+
+extern transitioning runtime ConstructAggregateErrorHelper(
+ Context, JSFunction, JSAny, Object): JSObject;
+
+extern transitioning runtime ConstructInternalAggregateErrorHelper(
+ Context, Object): JSObject;
+}
diff --git a/chromium/v8/src/builtins/array-join.tq b/chromium/v8/src/builtins/array-join.tq
index 08d0cbf894b..7bf74e4e317 100644
--- a/chromium/v8/src/builtins/array-join.tq
+++ b/chromium/v8/src/builtins/array-join.tq
@@ -296,7 +296,7 @@ transitioning macro ArrayJoinImpl<T: type>(implicit context: Context)(
}
case (obj: JSAny): {
if (IsNullOrUndefined(obj)) continue;
- next = ToString(context, obj);
+ next = string::ToString(context, obj);
}
}
}
@@ -418,7 +418,7 @@ macro LoadJoinStack(implicit context: Context)(): FixedArray
const stack: HeapObject = UnsafeCast<HeapObject>(
nativeContext[NativeContextSlot::ARRAY_JOIN_STACK_INDEX]);
if (stack == Undefined) goto IfUninitialized;
- assert(IsFixedArray(stack));
+ assert(Is<FixedArray>(stack));
return UnsafeCast<FixedArray>(stack);
}
diff --git a/chromium/v8/src/builtins/array-slice.tq b/chromium/v8/src/builtins/array-slice.tq
index 147dae6f72f..97026586adf 100644
--- a/chromium/v8/src/builtins/array-slice.tq
+++ b/chromium/v8/src/builtins/array-slice.tq
@@ -36,21 +36,18 @@ macro HandleFastAliasedSloppyArgumentsSlice(
const sloppyElements: SloppyArgumentsElements =
Cast<SloppyArgumentsElements>(args.elements) otherwise Bailout;
- const sloppyElementsLength: Smi = sloppyElements.length;
- const parameterMapLength: Smi =
- sloppyElementsLength - kSloppyArgumentsParameterMapStart;
+ const parameterMapLength: Smi = sloppyElements.length;
// Check to make sure that the extraction will not access outside the
// defined arguments
const end: Smi = start + count;
const unmappedElements: FixedArray =
- Cast<FixedArray>(sloppyElements.objects[kSloppyArgumentsArgumentsIndex])
+ Cast<FixedArray>(sloppyElements.arguments)
otherwise Bailout;
const unmappedElementsLength: Smi = unmappedElements.length;
if (SmiAbove(end, unmappedElementsLength)) goto Bailout;
- const argumentsContext: Context =
- UnsafeCast<Context>(sloppyElements.objects[kSloppyArgumentsContextIndex]);
+ const argumentsContext: Context = sloppyElements.context;
const arrayMap: Map =
LoadJSArrayElementsMap(ElementsKind::HOLEY_ELEMENTS, context);
@@ -63,8 +60,7 @@ macro HandleFastAliasedSloppyArgumentsSlice(
// Fill in the part of the result that map to context-mapped parameters.
for (let current: Smi = start; current < to; ++current) {
- const e: Object =
- sloppyElements.objects[current + kSloppyArgumentsParameterMapStart];
+ const e: Object = sloppyElements.mapped_entries[current];
const newElement = UnsafeCast<(JSAny | TheHole)>(
e != TheHole ? argumentsContext[UnsafeCast<Smi>(e)] :
unmappedElements.objects[current]);
diff --git a/chromium/v8/src/builtins/base.tq b/chromium/v8/src/builtins/base.tq
index 1d2c4546461..b42923412b1 100644
--- a/chromium/v8/src/builtins/base.tq
+++ b/chromium/v8/src/builtins/base.tq
@@ -78,7 +78,8 @@ type JSPrimitive = Numeric|String|Symbol|Boolean|Null|Undefined;
// TheHole or FixedArray.
type JSAny = JSReceiver|JSPrimitive;
-type JSAnyNotNumber = BigInt|String|Symbol|Boolean|Null|Undefined|JSReceiver;
+type JSAnyNotNumeric = String|Symbol|Boolean|Null|Undefined|JSReceiver;
+type JSAnyNotNumber = BigInt|JSAnyNotNumeric;
// This is the intersection of JSAny and HeapObject.
type JSAnyNotSmi = JSAnyNotNumber|HeapNumber;
@@ -134,6 +135,7 @@ const kDoubleHole: float64_or_hole = float64_or_hole{is_hole: true, value: 0};
// The HashTable inheritance hierarchy doesn't actually look like this in C++
// because it uses some class templates that we can't yet (and may never)
// express in Torque, but this is the expected organization of instance types.
+@doNotGenerateCast
extern class HashTable extends FixedArray generates 'TNode<FixedArray>';
extern class OrderedHashMap extends HashTable;
extern class OrderedHashSet extends HashTable;
@@ -264,6 +266,7 @@ extern enum MessageTemplate {
kNotGeneric,
kCalledNonCallable,
kCalledOnNullOrUndefined,
+ kCannotConvertToPrimitive,
kProtoObjectOrNull,
kInvalidOffset,
kInvalidTypedArrayLength,
@@ -307,6 +310,7 @@ extern enum MessageTemplate {
kProxyGetPrototypeOfNonExtensible,
kProxySetPrototypeOfNonExtensible,
kProxyDeletePropertyNonExtensible,
+ kUndefinedOrNullToObject,
kWeakRefsCleanupMustBeCallable,
kWasmTrapUnreachable,
kWasmTrapMemOutOfBounds,
@@ -320,14 +324,24 @@ extern enum MessageTemplate {
kWasmTrapDataSegmentDropped,
kWasmTrapElemSegmentDropped,
kWasmTrapTableOutOfBounds,
- kWasmTrapBrOnExnNullRef,
- kWasmTrapRethrowNullRef,
+ kWasmTrapBrOnExnNull,
+ kWasmTrapRethrowNull,
kWasmTrapNullDereference,
kWasmTrapIllegalCast,
kWasmTrapArrayOutOfBounds,
...
}
+extern enum PropertyAttributes extends int31 {
+ NONE,
+ READ_ONLY,
+ DONT_ENUM,
+ DONT_DELETE,
+ ALL_ATTRIBUTES_MASK,
+ FROZEN,
+ ...
+}
+
const kMaxArrayIndex:
constexpr uint32 generates 'JSArray::kMaxArrayIndex';
const kArrayBufferMaxByteLength:
@@ -364,12 +378,6 @@ const kMaxRegularHeapObjectSize: constexpr int31
const kMaxNewSpaceFixedArrayElements: constexpr int31
generates 'FixedArray::kMaxRegularLength';
-const kSloppyArgumentsArgumentsIndex: constexpr int31
- generates 'SloppyArgumentsElements::kArgumentsIndex';
-const kSloppyArgumentsContextIndex: constexpr int31
- generates 'SloppyArgumentsElements::kContextIndex';
-const kSloppyArgumentsParameterMapStart: constexpr int31
- generates 'SloppyArgumentsElements::kParameterMapStart';
extern enum PrimitiveType { kString, kBoolean, kSymbol, kNumber }
@@ -387,7 +395,9 @@ type Boolean = True|False;
type NumberOrUndefined = Number|Undefined;
+extern macro DefaultStringConstant(): String;
extern macro EmptyStringConstant(): EmptyString;
+extern macro ErrorsStringConstant(): String;
extern macro FalseConstant(): False;
extern macro Int32FalseConstant(): bool;
extern macro Int32TrueConstant(): bool;
@@ -396,11 +406,17 @@ extern macro LengthStringConstant(): String;
extern macro MatchSymbolConstant(): Symbol;
extern macro MessageStringConstant(): String;
extern macro NanConstant(): NaN;
+extern macro NameStringConstant(): String;
extern macro NullConstant(): Null;
+extern macro NumberStringConstant(): String;
extern macro ReturnStringConstant(): String;
+extern macro StringStringConstant(): String;
extern macro TheHoleConstant(): TheHole;
+extern macro ToPrimitiveSymbolConstant(): PublicSymbol;
+extern macro ToStringStringConstant(): String;
extern macro TrueConstant(): True;
extern macro UndefinedConstant(): Undefined;
+extern macro ValueOfStringConstant(): String;
const TheHole: TheHole = TheHoleConstant();
const Null: Null = NullConstant();
@@ -459,7 +475,7 @@ extern macro Print(Object);
extern macro DebugBreak();
// ES6 7.1.4 ToInteger ( argument )
-transitioning macro ToIntegerImpl(implicit context: Context)(input: Object):
+transitioning macro ToIntegerImpl(implicit context: Context)(input: JSAny):
Number {
let input = input;
@@ -478,28 +494,28 @@ transitioning macro ToIntegerImpl(implicit context: Context)(input: Object):
assert(IsNumberNormalized(result));
return result;
}
- case (ho: HeapObject): {
- input = math::NonNumberToNumber(ho);
+ case (a: JSAnyNotNumber): {
+ input = conversion::NonNumberToNumber(a);
}
}
}
unreachable;
}
-transitioning builtin ToInteger(implicit context: Context)(input: Object):
+transitioning builtin ToInteger(implicit context: Context)(input: JSAny):
Number {
return ToIntegerImpl(input);
}
@export
-transitioning macro ToInteger_Inline(implicit context: Context)(input: Object):
+transitioning macro ToInteger_Inline(implicit context: Context)(input: JSAny):
Number {
typeswitch (input) {
case (s: Smi): {
return s;
}
- case (ho: HeapObject): {
- return ToInteger(ho);
+ case (JSAny): {
+ return ToInteger(input);
}
}
}
@@ -518,6 +534,8 @@ extern transitioning macro GetProperty(implicit context: Context)(
JSAny, JSAny): JSAny;
extern transitioning builtin SetProperty(implicit context: Context)(
JSAny, JSAny, JSAny): JSAny;
+extern transitioning builtin SetPropertyIgnoreAttributes(
+ implicit context: Context)(JSObject, String, JSAny, Smi): JSAny;
extern transitioning builtin SetPropertyInLiteral(implicit context: Context)(
JSAny, JSAny, JSAny): JSAny;
extern transitioning builtin DeleteProperty(implicit context: Context)(
@@ -529,6 +547,8 @@ extern transitioning macro HasProperty_Inline(implicit context: Context)(
extern builtin LoadIC(
Context, JSAny, JSAny, TaggedIndex, FeedbackVector): JSAny;
+extern macro SetPropertyStrict(Context, Object, Object, Object): Object;
+
extern macro ThrowRangeError(implicit context: Context)(
constexpr MessageTemplate): never;
extern macro ThrowRangeError(implicit context: Context)(
@@ -581,10 +601,6 @@ extern builtin ToObject(Context, JSAny): JSReceiver;
extern macro ToObject_Inline(Context, JSAny): JSReceiver;
extern macro IsNullOrUndefined(Object): bool;
extern macro IsString(HeapObject): bool;
-transitioning builtin ToString(context: Context, o: JSAny): String {
- return ToStringImpl(context, o);
-}
-extern transitioning runtime ToStringRT(Context, JSAny): String;
extern transitioning builtin NonPrimitiveToPrimitive_String(
Context, JSAny): JSPrimitive;
extern transitioning builtin NonPrimitiveToPrimitive_Default(
@@ -616,6 +632,18 @@ extern macro StringCharCodeAt(String, uintptr): int32;
extern runtime StringCompareSequence(Context, String, String, Number): Boolean;
extern macro StringFromSingleCharCode(int32): String;
+extern macro NumberToString(Number): String;
+extern macro StringToNumber(String): Number;
+extern transitioning macro NonNumberToNumber(implicit context: Context)(
+ JSAnyNotNumber): Number;
+extern transitioning macro NonNumberToNumeric(implicit context: Context)(
+ JSAnyNotNumber): Numeric;
+
+extern macro Equal(JSAny, JSAny, Context): Boolean;
+macro Equal(implicit context: Context)(left: JSAny, right: JSAny): Boolean {
+ return Equal(left, right);
+}
+
extern macro StrictEqual(JSAny, JSAny): Boolean;
extern macro SmiLexicographicCompare(Smi, Smi): Smi;
extern runtime ReThrow(Context, JSAny): never;
@@ -778,6 +806,8 @@ extern operator '+' macro ConstexprInt31Add(
constexpr int31, constexpr int31): constexpr int31;
extern operator '*' macro ConstexprInt31Mul(
constexpr int31, constexpr int31): constexpr int31;
+extern operator '-' macro Int32Sub(int16, int16): int32;
+extern operator '-' macro Int32Sub(uint16, uint16): int32;
extern operator '-' macro Int32Sub(int32, int32): int32;
extern operator '*' macro Int32Mul(int32, int32): int32;
extern operator '/' macro Int32Div(int32, int32): int32;
@@ -814,6 +844,7 @@ extern operator '+' macro Float64Add(float64, float64): float64;
extern operator '-' macro Float64Sub(float64, float64): float64;
extern operator '*' macro Float64Mul(float64, float64): float64;
extern operator '/' macro Float64Div(float64, float64): float64;
+extern operator '%' macro Float64Mod(float64, float64): float64;
extern operator '+' macro NumberAdd(Number, Number): Number;
extern operator '-' macro NumberSub(Number, Number): Number;
@@ -850,6 +881,12 @@ extern operator '!' macro ConstexprBoolNot(constexpr bool): constexpr bool;
extern operator '!' macro Word32BinaryNot(bool): bool;
extern operator '!' macro IsFalse(Boolean): bool;
+extern operator '==' macro
+ConstexprInt31Equal(
+ constexpr InstanceType, constexpr InstanceType): constexpr bool;
+extern operator '-' macro ConstexprUint32Sub(
+ constexpr InstanceType, constexpr InstanceType): constexpr int32;
+
extern operator '.instanceType' macro LoadInstanceType(HeapObject):
InstanceType;
@@ -882,6 +919,7 @@ extern macro TaggedIsNotSmi(Object): bool;
extern macro TaggedIsPositiveSmi(Object): bool;
extern macro IsValidPositiveSmi(intptr): bool;
+extern macro IsInteger(JSAny): bool;
extern macro IsInteger(HeapNumber): bool;
extern macro AllocateHeapNumberWithValue(float64): HeapNumber;
@@ -912,6 +950,7 @@ macro SmiTag<T : type extends uint31>(value: T): SmiTagged<T> {
return %RawDownCast<SmiTagged<T>>(SmiFromUint32(value));
}
extern macro SmiToInt32(Smi): int32;
+extern macro SmiToFloat64(Smi): float64;
extern macro TaggedIndexToIntPtr(TaggedIndex): intptr;
extern macro IntPtrToTaggedIndex(intptr): TaggedIndex;
extern macro TaggedIndexToSmi(TaggedIndex): Smi;
@@ -919,6 +958,7 @@ extern macro SmiToTaggedIndex(Smi): TaggedIndex;
extern macro RoundIntPtrToFloat64(intptr): float64;
extern macro ChangeFloat32ToFloat64(float32): float64;
extern macro ChangeNumberToFloat64(Number): float64;
+extern macro ChangeNumberToUint32(Number): uint32;
extern macro ChangeTaggedNonSmiToInt32(implicit context: Context)(JSAnyNotSmi):
int32;
extern macro ChangeTaggedToFloat64(implicit context: Context)(JSAny): float64;
@@ -938,6 +978,7 @@ extern macro NumberConstant(constexpr int32): Number;
extern macro NumberConstant(constexpr uint32): Number;
extern macro IntPtrConstant(constexpr int31): intptr;
extern macro IntPtrConstant(constexpr int32): intptr;
+extern macro Uint16Constant(constexpr uint16): uint16;
extern macro Int32Constant(constexpr int31): int31;
extern macro Int32Constant(constexpr int32): int32;
extern macro Float64Constant(constexpr int31): float64;
@@ -962,22 +1003,6 @@ extern macro BitcastWordToTagged(uintptr): Object;
extern macro BitcastTaggedToWord(Tagged): intptr;
extern macro BitcastTaggedToWordForTagAndSmiBits(Tagged): intptr;
-macro Is<A : type extends Object, B : type extends Object>(
- implicit context: Context)(o: B): bool {
- Cast<A>(o) otherwise return false;
- return true;
-}
-
-macro UnsafeCast<A : type extends Object>(implicit context: Context)(o: Object):
- A {
- assert(Is<A>(o));
- return %RawDownCast<A>(o);
-}
-
-macro UnsafeConstCast<T: type>(r: const &T):&T {
- return %RawDownCast<&T>(r);
-}
-
extern macro FixedArrayMapConstant(): Map;
extern macro FixedDoubleArrayMapConstant(): Map;
extern macro FixedCOWArrayMapConstant(): Map;
@@ -986,7 +1011,6 @@ extern macro EmptyFixedArrayConstant(): EmptyFixedArray;
extern macro PromiseCapabilityMapConstant(): Map;
extern macro OneByteStringMapConstant(): Map;
extern macro StringMapConstant(): Map;
-extern macro SloppyArgumentsElementsMapConstant(): Map;
const kFixedArrayMap: Map = FixedArrayMapConstant();
const kFixedDoubleArrayMap: Map = FixedDoubleArrayMapConstant();
@@ -998,7 +1022,6 @@ const kPromiseCapabilityMap: Map = PromiseCapabilityMapConstant();
const kOneByteStringMap: Map = OneByteStringMapConstant();
// The map of a non-internalized internal SeqTwoByteString.
const kStringMap: Map = StringMapConstant();
-const kSloppyArgumentsElementsMap: Map = SloppyArgumentsElementsMapConstant();
extern macro IsPrototypeInitialArrayPrototype(implicit context: Context)(Map):
bool;
@@ -1371,7 +1394,6 @@ transitioning macro GetMethod(implicit context: Context)(
MessageTemplate::kPropertyNotFunction, value, symbol, o);
}
-extern macro NumberToString(Number): String;
extern macro IsOneByteStringInstanceType(InstanceType): bool;
// After converting an index to an integer, calculate a relative index:
@@ -1514,6 +1536,9 @@ macro IsFastJSArrayForReadWithNoCustomIteration(context: Context, o: Object):
extern transitioning runtime
CreateDataProperty(implicit context: Context)(JSReceiver, JSAny, JSAny);
+extern transitioning runtime SetOwnPropertyIgnoreAttributes(
+ implicit context: Context)(JSObject, String, JSAny, Smi);
+
namespace runtime {
extern runtime
GetDerivedMap(Context, JSFunction, JSReceiver): Map;
@@ -1573,35 +1598,6 @@ transitioning builtin FastCreateDataProperty(implicit context: Context)(
return Undefined;
}
-@export
-transitioning macro ToStringImpl(context: Context, o: JSAny): String {
- let result: JSAny = o;
- while (true) {
- typeswitch (result) {
- case (num: Number): {
- return NumberToString(num);
- }
- case (str: String): {
- return str;
- }
- case (oddball: Oddball): {
- return oddball.to_string;
- }
- case (JSReceiver): {
- result = NonPrimitiveToPrimitive_String(context, result);
- continue;
- }
- case (Symbol): {
- ThrowTypeError(MessageTemplate::kSymbolToString);
- }
- case (JSAny): {
- return ToStringRT(context, o);
- }
- }
- }
- unreachable;
-}
-
macro VerifiedUnreachable(): never {
StaticAssert(false);
unreachable;
diff --git a/chromium/v8/src/builtins/bigint.tq b/chromium/v8/src/builtins/bigint.tq
index d52de7f84ea..409301dcc98 100644
--- a/chromium/v8/src/builtins/bigint.tq
+++ b/chromium/v8/src/builtins/bigint.tq
@@ -13,6 +13,7 @@ type BigInt extends BigIntBase;
@noVerifier
@hasSameInstanceTypeAsParent
+@doNotGenerateCast
extern class MutableBigInt extends BigIntBase generates 'TNode<BigInt>' {
}
diff --git a/chromium/v8/src/builtins/builtins-array-gen.cc b/chromium/v8/src/builtins/builtins-array-gen.cc
index 734b9b634a0..dfd52255830 100644
--- a/chromium/v8/src/builtins/builtins-array-gen.cc
+++ b/chromium/v8/src/builtins/builtins-array-gen.cc
@@ -438,7 +438,6 @@ TF_BUILTIN(ArrayPrototypePush, CodeStubAssembler) {
}
TF_BUILTIN(ExtractFastJSArray, ArrayBuiltinsAssembler) {
- ParameterMode mode = OptimalParameterMode();
TNode<Context> context = CAST(Parameter(Descriptor::kContext));
TNode<JSArray> array = CAST(Parameter(Descriptor::kSource));
TNode<BInt> begin = SmiToBInt(CAST(Parameter(Descriptor::kBegin)));
@@ -446,7 +445,7 @@ TF_BUILTIN(ExtractFastJSArray, ArrayBuiltinsAssembler) {
CSA_ASSERT(this, Word32BinaryNot(IsNoElementsProtectorCellInvalid()));
- Return(ExtractFastJSArray(context, array, begin, count, mode));
+ Return(ExtractFastJSArray(context, array, begin, count));
}
TF_BUILTIN(CloneFastJSArray, ArrayBuiltinsAssembler) {
@@ -477,7 +476,7 @@ TF_BUILTIN(CloneFastJSArrayFillingHoles, ArrayBuiltinsAssembler) {
LoadElementsKind(array))),
Word32BinaryNot(IsNoElementsProtectorCellInvalid())));
- Return(CloneFastJSArray(context, array, {},
+ Return(CloneFastJSArray(context, array, base::nullopt,
HoleConversionMode::kConvertToUndefined));
}
@@ -1153,7 +1152,7 @@ TF_BUILTIN(ArrayIndexOfHoleyDoubles, ArrayIncludesIndexofAssembler) {
// ES #sec-array.prototype.values
TF_BUILTIN(ArrayPrototypeValues, CodeStubAssembler) {
- TNode<Context> context = CAST(Parameter(Descriptor::kContext));
+ TNode<NativeContext> context = CAST(Parameter(Descriptor::kContext));
TNode<Object> receiver = CAST(Parameter(Descriptor::kReceiver));
Return(CreateArrayIterator(context, ToObject_Inline(context, receiver),
IterationKind::kValues));
@@ -1161,7 +1160,7 @@ TF_BUILTIN(ArrayPrototypeValues, CodeStubAssembler) {
// ES #sec-array.prototype.entries
TF_BUILTIN(ArrayPrototypeEntries, CodeStubAssembler) {
- TNode<Context> context = CAST(Parameter(Descriptor::kContext));
+ TNode<NativeContext> context = CAST(Parameter(Descriptor::kContext));
TNode<Object> receiver = CAST(Parameter(Descriptor::kReceiver));
Return(CreateArrayIterator(context, ToObject_Inline(context, receiver),
IterationKind::kEntries));
@@ -1169,7 +1168,7 @@ TF_BUILTIN(ArrayPrototypeEntries, CodeStubAssembler) {
// ES #sec-array.prototype.keys
TF_BUILTIN(ArrayPrototypeKeys, CodeStubAssembler) {
- TNode<Context> context = CAST(Parameter(Descriptor::kContext));
+ TNode<NativeContext> context = CAST(Parameter(Descriptor::kContext));
TNode<Object> receiver = CAST(Parameter(Descriptor::kReceiver));
Return(CreateArrayIterator(context, ToObject_Inline(context, receiver),
IterationKind::kKeys));
@@ -1665,7 +1664,8 @@ void ArrayBuiltinsAssembler::TailCallArrayConstructorStub(
void ArrayBuiltinsAssembler::CreateArrayDispatchNoArgument(
TNode<Context> context, TNode<JSFunction> target, TNode<Int32T> argc,
- AllocationSiteOverrideMode mode, TNode<AllocationSite> allocation_site) {
+ AllocationSiteOverrideMode mode,
+ base::Optional<TNode<AllocationSite>> allocation_site) {
if (mode == DISABLE_ALLOCATION_SITES) {
Callable callable = CodeFactory::ArrayNoArgumentConstructor(
isolate(), GetInitialFastElementsKind(), mode);
@@ -1674,7 +1674,8 @@ void ArrayBuiltinsAssembler::CreateArrayDispatchNoArgument(
argc);
} else {
DCHECK_EQ(mode, DONT_OVERRIDE);
- TNode<Int32T> elements_kind = LoadElementsKind(allocation_site);
+ DCHECK(allocation_site);
+ TNode<Int32T> elements_kind = LoadElementsKind(*allocation_site);
// TODO(ishell): Compute the builtin index dynamically instead of
// iterating over all expected elements kinds.
@@ -1688,7 +1689,7 @@ void ArrayBuiltinsAssembler::CreateArrayDispatchNoArgument(
Callable callable =
CodeFactory::ArrayNoArgumentConstructor(isolate(), kind, mode);
- TailCallArrayConstructorStub(callable, context, target, allocation_site,
+ TailCallArrayConstructorStub(callable, context, target, *allocation_site,
argc);
BIND(&next);
@@ -1701,7 +1702,8 @@ void ArrayBuiltinsAssembler::CreateArrayDispatchNoArgument(
void ArrayBuiltinsAssembler::CreateArrayDispatchSingleArgument(
TNode<Context> context, TNode<JSFunction> target, TNode<Int32T> argc,
- AllocationSiteOverrideMode mode, TNode<AllocationSite> allocation_site) {
+ AllocationSiteOverrideMode mode,
+ base::Optional<TNode<AllocationSite>> allocation_site) {
if (mode == DISABLE_ALLOCATION_SITES) {
ElementsKind initial = GetInitialFastElementsKind();
ElementsKind holey_initial = GetHoleyElementsKind(initial);
@@ -1712,7 +1714,8 @@ void ArrayBuiltinsAssembler::CreateArrayDispatchSingleArgument(
argc);
} else {
DCHECK_EQ(mode, DONT_OVERRIDE);
- TNode<Smi> transition_info = LoadTransitionInfo(allocation_site);
+ DCHECK(allocation_site);
+ TNode<Smi> transition_info = LoadTransitionInfo(*allocation_site);
// Least significant bit in fast array elements kind means holeyness.
STATIC_ASSERT(PACKED_SMI_ELEMENTS == 0);
@@ -1735,7 +1738,7 @@ void ArrayBuiltinsAssembler::CreateArrayDispatchSingleArgument(
// Make elements kind holey and update elements kind in the type info.
var_elements_kind = Word32Or(var_elements_kind.value(), Int32Constant(1));
StoreObjectFieldNoWriteBarrier(
- allocation_site, AllocationSite::kTransitionInfoOrBoilerplateOffset,
+ *allocation_site, AllocationSite::kTransitionInfoOrBoilerplateOffset,
SmiOr(transition_info, SmiConstant(fast_elements_kind_holey_mask)));
Goto(&normal_sequence);
}
@@ -1756,7 +1759,7 @@ void ArrayBuiltinsAssembler::CreateArrayDispatchSingleArgument(
Callable callable =
CodeFactory::ArraySingleArgumentConstructor(isolate(), kind, mode);
- TailCallArrayConstructorStub(callable, context, target, allocation_site,
+ TailCallArrayConstructorStub(callable, context, target, *allocation_site,
argc);
BIND(&next);
@@ -1769,7 +1772,8 @@ void ArrayBuiltinsAssembler::CreateArrayDispatchSingleArgument(
void ArrayBuiltinsAssembler::GenerateDispatchToArrayStub(
TNode<Context> context, TNode<JSFunction> target, TNode<Int32T> argc,
- AllocationSiteOverrideMode mode, TNode<AllocationSite> allocation_site) {
+ AllocationSiteOverrideMode mode,
+ base::Optional<TNode<AllocationSite>> allocation_site) {
Label check_one_case(this), fallthrough(this);
GotoIfNot(Word32Equal(argc, Int32Constant(0)), &check_one_case);
CreateArrayDispatchNoArgument(context, target, argc, mode, allocation_site);
@@ -1862,8 +1866,9 @@ void ArrayBuiltinsAssembler::GenerateConstructor(
{
TNode<JSArray> array = AllocateJSArray(
elements_kind, array_map, array_size_smi, array_size_smi,
- mode == DONT_TRACK_ALLOCATION_SITE ? TNode<AllocationSite>()
- : CAST(allocation_site));
+ mode == DONT_TRACK_ALLOCATION_SITE
+ ? base::Optional<TNode<AllocationSite>>(base::nullopt)
+ : CAST(allocation_site));
Return(array);
}
}
@@ -1882,9 +1887,10 @@ void ArrayBuiltinsAssembler::GenerateArrayNoArgumentConstructor(
Parameter(Descriptor::kFunction), JSFunction::kContextOffset));
bool track_allocation_site =
AllocationSite::ShouldTrack(kind) && mode != DISABLE_ALLOCATION_SITES;
- TNode<AllocationSite> allocation_site =
- track_allocation_site ? CAST(Parameter(Descriptor::kAllocationSite))
- : TNode<AllocationSite>();
+ base::Optional<TNode<AllocationSite>> allocation_site =
+ track_allocation_site
+ ? CAST(Parameter(Descriptor::kAllocationSite))
+ : base::Optional<TNode<AllocationSite>>(base::nullopt);
TNode<Map> array_map = LoadJSArrayElementsMap(kind, native_context);
TNode<JSArray> array = AllocateJSArray(
kind, array_map, IntPtrConstant(JSArray::kPreallocatedArrayElements),
diff --git a/chromium/v8/src/builtins/builtins-array-gen.h b/chromium/v8/src/builtins/builtins-array-gen.h
index 088af90665d..96833d9dea2 100644
--- a/chromium/v8/src/builtins/builtins-array-gen.h
+++ b/chromium/v8/src/builtins/builtins-array-gen.h
@@ -72,20 +72,20 @@ class ArrayBuiltinsAssembler : public CodeStubAssembler {
TNode<JSFunction> target, TNode<HeapObject> allocation_site_or_undefined,
TNode<Int32T> argc);
- void GenerateDispatchToArrayStub(TNode<Context> context,
- TNode<JSFunction> target, TNode<Int32T> argc,
- AllocationSiteOverrideMode mode,
- TNode<AllocationSite> allocation_site = {});
+ void GenerateDispatchToArrayStub(
+ TNode<Context> context, TNode<JSFunction> target, TNode<Int32T> argc,
+ AllocationSiteOverrideMode mode,
+ base::Optional<TNode<AllocationSite>> allocation_site = base::nullopt);
void CreateArrayDispatchNoArgument(
TNode<Context> context, TNode<JSFunction> target, TNode<Int32T> argc,
AllocationSiteOverrideMode mode,
- TNode<AllocationSite> allocation_site = {});
+ base::Optional<TNode<AllocationSite>> allocation_site);
void CreateArrayDispatchSingleArgument(
TNode<Context> context, TNode<JSFunction> target, TNode<Int32T> argc,
AllocationSiteOverrideMode mode,
- TNode<AllocationSite> allocation_site = {});
+ base::Optional<TNode<AllocationSite>> allocation_site);
void GenerateConstructor(TNode<Context> context,
TNode<HeapObject> array_function,
diff --git a/chromium/v8/src/builtins/builtins-async-iterator-gen.cc b/chromium/v8/src/builtins/builtins-async-iterator-gen.cc
index b138515af65..73e5605ccc4 100644
--- a/chromium/v8/src/builtins/builtins-async-iterator-gen.cc
+++ b/chromium/v8/src/builtins/builtins-async-iterator-gen.cc
@@ -16,6 +16,10 @@ namespace internal {
namespace {
class AsyncFromSyncBuiltinsAssembler : public AsyncBuiltinsAssembler {
public:
+ // The 'next' and 'return' take an optional value parameter, and the 'throw'
+ // method take an optional reason parameter.
+ static const int kValueOrReasonArg = 0;
+
explicit AsyncFromSyncBuiltinsAssembler(compiler::CodeAssemblerState* state)
: AsyncBuiltinsAssembler(state) {}
@@ -31,8 +35,8 @@ class AsyncFromSyncBuiltinsAssembler : public AsyncBuiltinsAssembler {
using SyncIteratorNodeGenerator =
std::function<TNode<Object>(TNode<JSReceiver>)>;
void Generate_AsyncFromSyncIteratorMethod(
- const TNode<Context> context, const TNode<Object> iterator,
- const TNode<Object> sent_value,
+ CodeStubArguments* args, const TNode<Context> context,
+ const TNode<Object> iterator, const TNode<Object> sent_value,
const SyncIteratorNodeGenerator& get_method,
const UndefinedMethodHandler& if_method_undefined,
const char* operation_name,
@@ -40,9 +44,9 @@ class AsyncFromSyncBuiltinsAssembler : public AsyncBuiltinsAssembler {
base::Optional<TNode<Object>> initial_exception_value = base::nullopt);
void Generate_AsyncFromSyncIteratorMethod(
- const TNode<Context> context, const TNode<Object> iterator,
- const TNode<Object> sent_value, Handle<String> name,
- const UndefinedMethodHandler& if_method_undefined,
+ CodeStubArguments* args, const TNode<Context> context,
+ const TNode<Object> iterator, const TNode<Object> sent_value,
+ Handle<String> name, const UndefinedMethodHandler& if_method_undefined,
const char* operation_name,
Label::Type reject_label_type = Label::kDeferred,
base::Optional<TNode<Object>> initial_exception_value = base::nullopt) {
@@ -50,7 +54,7 @@ class AsyncFromSyncBuiltinsAssembler : public AsyncBuiltinsAssembler {
return GetProperty(context, sync_iterator, name);
};
return Generate_AsyncFromSyncIteratorMethod(
- context, iterator, sent_value, get_method, if_method_undefined,
+ args, context, iterator, sent_value, get_method, if_method_undefined,
operation_name, reject_label_type, initial_exception_value);
}
@@ -97,8 +101,9 @@ void AsyncFromSyncBuiltinsAssembler::ThrowIfNotAsyncFromSyncIterator(
}
void AsyncFromSyncBuiltinsAssembler::Generate_AsyncFromSyncIteratorMethod(
- const TNode<Context> context, const TNode<Object> iterator,
- const TNode<Object> sent_value, const SyncIteratorNodeGenerator& get_method,
+ CodeStubArguments* args, const TNode<Context> context,
+ const TNode<Object> iterator, const TNode<Object> sent_value,
+ const SyncIteratorNodeGenerator& get_method,
const UndefinedMethodHandler& if_method_undefined,
const char* operation_name, Label::Type reject_label_type,
base::Optional<TNode<Object>> initial_exception_value) {
@@ -122,22 +127,37 @@ void AsyncFromSyncBuiltinsAssembler::Generate_AsyncFromSyncIteratorMethod(
if (if_method_undefined) {
Label if_isnotundefined(this);
- GotoIfNot(IsUndefined(method), &if_isnotundefined);
+ GotoIfNot(IsNullOrUndefined(method), &if_isnotundefined);
if_method_undefined(native_context, promise, &reject_promise);
BIND(&if_isnotundefined);
}
- TNode<Object> iter_result;
+ TVARIABLE(Object, iter_result);
{
+ Label has_sent_value(this), no_sent_value(this), merge(this);
ScopedExceptionHandler handler(this, &reject_promise, &var_exception);
- iter_result = Call(context, method, sync_iterator, sent_value);
+ Branch(
+ IntPtrGreaterThan(args->GetLength(), IntPtrConstant(kValueOrReasonArg)),
+ &has_sent_value, &no_sent_value);
+ BIND(&has_sent_value);
+ {
+ iter_result = Call(context, method, sync_iterator, sent_value);
+ Goto(&merge);
+ }
+ BIND(&no_sent_value);
+ {
+ iter_result = Call(context, method, sync_iterator);
+ Goto(&merge);
+ }
+ BIND(&merge);
}
TNode<Object> value;
TNode<Oddball> done;
- std::tie(value, done) = LoadIteratorResult(
- context, native_context, iter_result, &reject_promise, &var_exception);
+ std::tie(value, done) =
+ LoadIteratorResult(context, native_context, iter_result.value(),
+ &reject_promise, &var_exception);
const TNode<JSFunction> promise_fun =
CAST(LoadContextElement(native_context, Context::PROMISE_FUNCTION_INDEX));
@@ -160,15 +180,16 @@ void AsyncFromSyncBuiltinsAssembler::Generate_AsyncFromSyncIteratorMethod(
// Perform ! PerformPromiseThen(valueWrapper,
// onFulfilled, undefined, promiseCapability).
- Return(CallBuiltin(Builtins::kPerformPromiseThen, context, value_wrapper,
- on_fulfilled, UndefinedConstant(), promise));
+ args->PopAndReturn(CallBuiltin(Builtins::kPerformPromiseThen, context,
+ value_wrapper, on_fulfilled,
+ UndefinedConstant(), promise));
BIND(&reject_promise);
{
const TNode<Object> exception = var_exception.value();
CallBuiltin(Builtins::kRejectPromise, context, promise, exception,
TrueConstant());
- Return(promise);
+ args->PopAndReturn(promise);
}
}
@@ -252,8 +273,12 @@ AsyncFromSyncBuiltinsAssembler::LoadIteratorResult(
// https://tc39.github.io/proposal-async-iteration/
// Section #sec-%asyncfromsynciteratorprototype%.next
TF_BUILTIN(AsyncFromSyncIteratorPrototypeNext, AsyncFromSyncBuiltinsAssembler) {
- const TNode<Object> iterator = CAST(Parameter(Descriptor::kReceiver));
- const TNode<Object> value = CAST(Parameter(Descriptor::kValue));
+ TNode<IntPtrT> argc = ChangeInt32ToIntPtr(
+ UncheckedCast<Int32T>(Parameter(Descriptor::kJSActualArgumentsCount)));
+ CodeStubArguments args(this, argc);
+
+ const TNode<Object> iterator = args.GetReceiver();
+ const TNode<Object> value = args.GetOptionalArgumentValue(kValueOrReasonArg);
const TNode<Context> context = CAST(Parameter(Descriptor::kContext));
auto get_method = [=](const TNode<JSReceiver> unused) {
@@ -261,7 +286,7 @@ TF_BUILTIN(AsyncFromSyncIteratorPrototypeNext, AsyncFromSyncBuiltinsAssembler) {
JSAsyncFromSyncIterator::kNextOffset);
};
Generate_AsyncFromSyncIteratorMethod(
- context, iterator, value, get_method, UndefinedMethodHandler(),
+ &args, context, iterator, value, get_method, UndefinedMethodHandler(),
"[Async-from-Sync Iterator].prototype.next");
}
@@ -269,11 +294,16 @@ TF_BUILTIN(AsyncFromSyncIteratorPrototypeNext, AsyncFromSyncBuiltinsAssembler) {
// Section #sec-%asyncfromsynciteratorprototype%.return
TF_BUILTIN(AsyncFromSyncIteratorPrototypeReturn,
AsyncFromSyncBuiltinsAssembler) {
- const TNode<Object> iterator = CAST(Parameter(Descriptor::kReceiver));
- const TNode<Object> value = CAST(Parameter(Descriptor::kValue));
+ TNode<IntPtrT> argc = ChangeInt32ToIntPtr(
+ UncheckedCast<Int32T>(Parameter(Descriptor::kJSActualArgumentsCount)));
+ CodeStubArguments args(this, argc);
+
+ const TNode<Object> iterator = args.GetReceiver();
+ const TNode<Object> value = args.GetOptionalArgumentValue(kValueOrReasonArg);
const TNode<Context> context = CAST(Parameter(Descriptor::kContext));
- auto if_return_undefined = [=](const TNode<NativeContext> native_context,
+ auto if_return_undefined = [=, &args](
+ const TNode<NativeContext> native_context,
const TNode<JSPromise> promise,
Label* if_exception) {
// If return is undefined, then
@@ -285,20 +315,24 @@ TF_BUILTIN(AsyncFromSyncIteratorPrototypeReturn,
// IfAbruptRejectPromise(nextDone, promiseCapability).
// Return promiseCapability.[[Promise]].
CallBuiltin(Builtins::kResolvePromise, context, promise, iter_result);
- Return(promise);
+ args.PopAndReturn(promise);
};
Generate_AsyncFromSyncIteratorMethod(
- context, iterator, value, factory()->return_string(), if_return_undefined,
- "[Async-from-Sync Iterator].prototype.return");
+ &args, context, iterator, value, factory()->return_string(),
+ if_return_undefined, "[Async-from-Sync Iterator].prototype.return");
}
// https://tc39.github.io/proposal-async-iteration/
// Section #sec-%asyncfromsynciteratorprototype%.throw
TF_BUILTIN(AsyncFromSyncIteratorPrototypeThrow,
AsyncFromSyncBuiltinsAssembler) {
- const TNode<Object> iterator = CAST(Parameter(Descriptor::kReceiver));
- const TNode<Object> reason = CAST(Parameter(Descriptor::kReason));
+ TNode<IntPtrT> argc = ChangeInt32ToIntPtr(
+ UncheckedCast<Int32T>(Parameter(Descriptor::kJSActualArgumentsCount)));
+ CodeStubArguments args(this, argc);
+
+ const TNode<Object> iterator = args.GetReceiver();
+ const TNode<Object> reason = args.GetOptionalArgumentValue(kValueOrReasonArg);
const TNode<Context> context = CAST(Parameter(Descriptor::kContext));
auto if_throw_undefined = [=](const TNode<NativeContext> native_context,
@@ -306,9 +340,9 @@ TF_BUILTIN(AsyncFromSyncIteratorPrototypeThrow,
Label* if_exception) { Goto(if_exception); };
Generate_AsyncFromSyncIteratorMethod(
- context, iterator, reason, factory()->throw_string(), if_throw_undefined,
- "[Async-from-Sync Iterator].prototype.throw", Label::kNonDeferred,
- reason);
+ &args, context, iterator, reason, factory()->throw_string(),
+ if_throw_undefined, "[Async-from-Sync Iterator].prototype.throw",
+ Label::kNonDeferred, reason);
}
} // namespace internal
diff --git a/chromium/v8/src/builtins/builtins-call-gen.cc b/chromium/v8/src/builtins/builtins-call-gen.cc
index d457e033149..f7919b78f47 100644
--- a/chromium/v8/src/builtins/builtins-call-gen.cc
+++ b/chromium/v8/src/builtins/builtins-call-gen.cc
@@ -64,6 +64,49 @@ void Builtins::Generate_CallFunctionForwardVarargs(MacroAssembler* masm) {
masm->isolate()->builtins()->CallFunction());
}
+TF_BUILTIN(Call_ReceiverIsNullOrUndefined_WithFeedback,
+ CallOrConstructBuiltinsAssembler) {
+ TNode<Object> target = CAST(Parameter(Descriptor::kFunction));
+ TNode<Int32T> argc =
+ UncheckedCast<Int32T>(Parameter(Descriptor::kActualArgumentsCount));
+ TNode<Context> context = CAST(Parameter(Descriptor::kContext));
+ TNode<HeapObject> maybe_feedback_vector =
+ CAST(Parameter(Descriptor::kMaybeFeedbackVector));
+ TNode<Int32T> slot = UncheckedCast<Int32T>(Parameter(Descriptor::kSlot));
+ CollectCallFeedback(target, context, maybe_feedback_vector,
+ Unsigned(ChangeInt32ToIntPtr(slot)));
+ TailCallBuiltin(Builtins::kCall_ReceiverIsNullOrUndefined, context, target,
+ argc);
+}
+
+TF_BUILTIN(Call_ReceiverIsNotNullOrUndefined_WithFeedback,
+ CallOrConstructBuiltinsAssembler) {
+ TNode<Object> target = CAST(Parameter(Descriptor::kFunction));
+ TNode<Int32T> argc =
+ UncheckedCast<Int32T>(Parameter(Descriptor::kActualArgumentsCount));
+ TNode<Context> context = CAST(Parameter(Descriptor::kContext));
+ TNode<HeapObject> maybe_feedback_vector =
+ CAST(Parameter(Descriptor::kMaybeFeedbackVector));
+ TNode<Int32T> slot = UncheckedCast<Int32T>(Parameter(Descriptor::kSlot));
+ CollectCallFeedback(target, context, maybe_feedback_vector,
+ Unsigned(ChangeInt32ToIntPtr(slot)));
+ TailCallBuiltin(Builtins::kCall_ReceiverIsNotNullOrUndefined, context, target,
+ argc);
+}
+
+TF_BUILTIN(Call_ReceiverIsAny_WithFeedback, CallOrConstructBuiltinsAssembler) {
+ TNode<Object> target = CAST(Parameter(Descriptor::kFunction));
+ TNode<Int32T> argc =
+ UncheckedCast<Int32T>(Parameter(Descriptor::kActualArgumentsCount));
+ TNode<Context> context = CAST(Parameter(Descriptor::kContext));
+ TNode<HeapObject> maybe_feedback_vector =
+ CAST(Parameter(Descriptor::kMaybeFeedbackVector));
+ TNode<Int32T> slot = UncheckedCast<Int32T>(Parameter(Descriptor::kSlot));
+ CollectCallFeedback(target, context, maybe_feedback_vector,
+ Unsigned(ChangeInt32ToIntPtr(slot)));
+ TailCallBuiltin(Builtins::kCall_ReceiverIsAny, context, target, argc);
+}
+
void CallOrConstructBuiltinsAssembler::CallOrConstructWithArrayLike(
TNode<Object> target, base::Optional<TNode<Object>> new_target,
TNode<Object> arguments_list, TNode<Context> context) {
@@ -387,6 +430,19 @@ TF_BUILTIN(CallWithArrayLike, CallOrConstructBuiltinsAssembler) {
CallOrConstructWithArrayLike(target, new_target, arguments_list, context);
}
+TF_BUILTIN(CallWithArrayLike_WithFeedback, CallOrConstructBuiltinsAssembler) {
+ TNode<Object> target = CAST(Parameter(Descriptor::kTarget));
+ base::Optional<TNode<Object>> new_target = base::nullopt;
+ TNode<Object> arguments_list = CAST(Parameter(Descriptor::kArgumentsList));
+ TNode<Context> context = CAST(Parameter(Descriptor::kContext));
+ TNode<HeapObject> maybe_feedback_vector =
+ CAST(Parameter(Descriptor::kMaybeFeedbackVector));
+ TNode<Int32T> slot = UncheckedCast<Int32T>(Parameter(Descriptor::kSlot));
+ CollectCallFeedback(target, context, maybe_feedback_vector,
+ Unsigned(ChangeInt32ToIntPtr(slot)));
+ CallOrConstructWithArrayLike(target, new_target, arguments_list, context);
+}
+
TF_BUILTIN(CallWithSpread, CallOrConstructBuiltinsAssembler) {
TNode<Object> target = CAST(Parameter(Descriptor::kTarget));
base::Optional<TNode<Object>> new_target = base::nullopt;
@@ -397,6 +453,21 @@ TF_BUILTIN(CallWithSpread, CallOrConstructBuiltinsAssembler) {
CallOrConstructWithSpread(target, new_target, spread, args_count, context);
}
+TF_BUILTIN(CallWithSpread_WithFeedback, CallOrConstructBuiltinsAssembler) {
+ TNode<Object> target = CAST(Parameter(Descriptor::kTarget));
+ base::Optional<TNode<Object>> new_target = base::nullopt;
+ TNode<Object> spread = CAST(Parameter(Descriptor::kSpread));
+ TNode<Int32T> args_count =
+ UncheckedCast<Int32T>(Parameter(Descriptor::kArgumentsCount));
+ TNode<Context> context = CAST(Parameter(Descriptor::kContext));
+ TNode<HeapObject> maybe_feedback_vector =
+ CAST(Parameter(Descriptor::kMaybeFeedbackVector));
+ TNode<Int32T> slot = UncheckedCast<Int32T>(Parameter(Descriptor::kSlot));
+ CollectCallFeedback(target, context, maybe_feedback_vector,
+ Unsigned(ChangeInt32ToIntPtr(slot)));
+ CallOrConstructWithSpread(target, new_target, spread, args_count, context);
+}
+
TNode<JSReceiver> CallOrConstructBuiltinsAssembler::GetCompatibleReceiver(
TNode<JSReceiver> receiver, TNode<HeapObject> signature,
TNode<Context> context) {
@@ -535,7 +606,7 @@ void CallOrConstructBuiltinsAssembler::CallFunctionTemplate(
TNode<IntPtrT> function_template_info_flags = LoadAndUntagObjectField(
function_template_info, FunctionTemplateInfo::kFlagOffset);
Branch(IsSetWord(function_template_info_flags,
- 1 << FunctionTemplateInfo::kAcceptAnyReceiver),
+ 1 << FunctionTemplateInfo::AcceptAnyReceiverBit::kShift),
&receiver_done, &receiver_needs_access_check);
BIND(&receiver_needs_access_check);
diff --git a/chromium/v8/src/builtins/builtins-collections-gen.cc b/chromium/v8/src/builtins/builtins-collections-gen.cc
index 2f0e5a75602..3ab4392b87c 100644
--- a/chromium/v8/src/builtins/builtins-collections-gen.cc
+++ b/chromium/v8/src/builtins/builtins-collections-gen.cc
@@ -761,7 +761,7 @@ void CollectionsBuiltinsAssembler::FindOrderedHashTableEntry(
const TNode<IntPtrT> number_of_buckets =
SmiUntag(CAST(UnsafeLoadFixedArrayElement(
table, CollectionType::NumberOfBucketsIndex())));
- const TNode<WordT> bucket =
+ const TNode<IntPtrT> bucket =
WordAnd(hash, IntPtrSub(number_of_buckets, IntPtrConstant(1)));
const TNode<IntPtrT> first_entry = SmiUntag(CAST(UnsafeLoadFixedArrayElement(
table, bucket, CollectionType::HashTableStartIndex() * kTaggedSize)));
diff --git a/chromium/v8/src/builtins/builtins-constructor-gen.cc b/chromium/v8/src/builtins/builtins-constructor-gen.cc
index c706ce9306c..4079bc75d14 100644
--- a/chromium/v8/src/builtins/builtins-constructor-gen.cc
+++ b/chromium/v8/src/builtins/builtins-constructor-gen.cc
@@ -36,6 +36,31 @@ void Builtins::Generate_ConstructFunctionForwardVarargs(MacroAssembler* masm) {
BUILTIN_CODE(masm->isolate(), ConstructFunction));
}
+TF_BUILTIN(Construct_WithFeedback, CallOrConstructBuiltinsAssembler) {
+ TNode<Object> target = CAST(Parameter(Descriptor::kTarget));
+ TNode<Object> new_target = CAST(Parameter(Descriptor::kNewTarget));
+ TNode<Int32T> argc =
+ UncheckedCast<Int32T>(Parameter(Descriptor::kActualArgumentsCount));
+ TNode<Context> context = CAST(Parameter(Descriptor::kContext));
+ TNode<HeapObject> maybe_feedback_vector =
+ CAST(Parameter(Descriptor::kMaybeFeedbackVector));
+ TNode<Int32T> slot = UncheckedCast<Int32T>(Parameter(Descriptor::kSlot));
+
+ TVARIABLE(AllocationSite, allocation_site);
+ Label if_construct_generic(this), if_construct_array(this);
+ CollectConstructFeedback(context, target, new_target, maybe_feedback_vector,
+ Unsigned(ChangeInt32ToIntPtr(slot)),
+ &if_construct_generic, &if_construct_array,
+ &allocation_site);
+
+ BIND(&if_construct_generic);
+ TailCallBuiltin(Builtins::kConstruct, context, target, new_target, argc);
+
+ BIND(&if_construct_array);
+ TailCallBuiltin(Builtins::kArrayConstructorImpl, context, target, new_target,
+ argc, allocation_site.value());
+}
+
TF_BUILTIN(ConstructWithArrayLike, CallOrConstructBuiltinsAssembler) {
TNode<Object> target = CAST(Parameter(Descriptor::kTarget));
TNode<Object> new_target = CAST(Parameter(Descriptor::kNewTarget));
@@ -44,6 +69,30 @@ TF_BUILTIN(ConstructWithArrayLike, CallOrConstructBuiltinsAssembler) {
CallOrConstructWithArrayLike(target, new_target, arguments_list, context);
}
+TF_BUILTIN(ConstructWithArrayLike_WithFeedback,
+ CallOrConstructBuiltinsAssembler) {
+ TNode<Object> target = CAST(Parameter(Descriptor::kTarget));
+ TNode<Object> new_target = CAST(Parameter(Descriptor::kNewTarget));
+ TNode<Object> arguments_list = CAST(Parameter(Descriptor::kArgumentsList));
+ TNode<Context> context = CAST(Parameter(Descriptor::kContext));
+ TNode<HeapObject> maybe_feedback_vector =
+ CAST(Parameter(Descriptor::kMaybeFeedbackVector));
+ TNode<Int32T> slot = UncheckedCast<Int32T>(Parameter(Descriptor::kSlot));
+
+ TVARIABLE(AllocationSite, allocation_site);
+ Label if_construct_generic(this), if_construct_array(this);
+ CollectConstructFeedback(context, target, new_target, maybe_feedback_vector,
+ Unsigned(ChangeInt32ToIntPtr(slot)),
+ &if_construct_generic, &if_construct_array,
+ &allocation_site);
+
+ BIND(&if_construct_array);
+ Goto(&if_construct_generic); // Not implemented.
+
+ BIND(&if_construct_generic);
+ CallOrConstructWithArrayLike(target, new_target, arguments_list, context);
+}
+
TF_BUILTIN(ConstructWithSpread, CallOrConstructBuiltinsAssembler) {
TNode<Object> target = CAST(Parameter(Descriptor::kTarget));
TNode<Object> new_target = CAST(Parameter(Descriptor::kNewTarget));
@@ -54,6 +103,31 @@ TF_BUILTIN(ConstructWithSpread, CallOrConstructBuiltinsAssembler) {
CallOrConstructWithSpread(target, new_target, spread, args_count, context);
}
+TF_BUILTIN(ConstructWithSpread_WithFeedback, CallOrConstructBuiltinsAssembler) {
+ TNode<Object> target = CAST(Parameter(Descriptor::kTarget));
+ TNode<Object> new_target = CAST(Parameter(Descriptor::kNewTarget));
+ TNode<Object> spread = CAST(Parameter(Descriptor::kSpread));
+ TNode<Int32T> args_count =
+ UncheckedCast<Int32T>(Parameter(Descriptor::kActualArgumentsCount));
+ TNode<Context> context = CAST(Parameter(Descriptor::kContext));
+ TNode<HeapObject> maybe_feedback_vector =
+ CAST(Parameter(Descriptor::kMaybeFeedbackVector));
+ TNode<Int32T> slot = UncheckedCast<Int32T>(Parameter(Descriptor::kSlot));
+
+ TVARIABLE(AllocationSite, allocation_site);
+ Label if_construct_generic(this), if_construct_array(this);
+ CollectConstructFeedback(context, target, new_target, maybe_feedback_vector,
+ Unsigned(ChangeInt32ToIntPtr(slot)),
+ &if_construct_generic, &if_construct_array,
+ &allocation_site);
+
+ BIND(&if_construct_array);
+ Goto(&if_construct_generic); // Not implemented.
+
+ BIND(&if_construct_generic);
+ CallOrConstructWithSpread(target, new_target, spread, args_count, context);
+}
+
using Node = compiler::Node;
TF_BUILTIN(FastNewClosure, ConstructorBuiltinsAssembler) {
@@ -691,6 +765,11 @@ TF_BUILTIN(ObjectConstructor, ConstructorBuiltinsAssembler) {
args.PopAndReturn(var_result.value());
}
+TF_BUILTIN(CreateEmptyLiteralObject, ConstructorBuiltinsAssembler) {
+ TNode<Context> context = CAST(Parameter(Descriptor::kContext));
+ Return(EmitCreateEmptyObjectLiteral(context));
+}
+
// ES #sec-number-constructor
TF_BUILTIN(NumberConstructor, ConstructorBuiltinsAssembler) {
TNode<Context> context = CAST(Parameter(Descriptor::kContext));
diff --git a/chromium/v8/src/builtins/builtins-conversion-gen.cc b/chromium/v8/src/builtins/builtins-conversion-gen.cc
index e524f39b5fd..54fa752969e 100644
--- a/chromium/v8/src/builtins/builtins-conversion-gen.cc
+++ b/chromium/v8/src/builtins/builtins-conversion-gen.cc
@@ -12,181 +12,6 @@
namespace v8 {
namespace internal {
-class ConversionBuiltinsAssembler : public CodeStubAssembler {
- public:
- explicit ConversionBuiltinsAssembler(compiler::CodeAssemblerState* state)
- : CodeStubAssembler(state) {}
-
- protected:
- void Generate_NonPrimitiveToPrimitive(TNode<Context> context,
- TNode<Object> input,
- ToPrimitiveHint hint);
-
- void Generate_OrdinaryToPrimitive(TNode<Context> context, TNode<Object> input,
- OrdinaryToPrimitiveHint hint);
-};
-
-// ES6 section 7.1.1 ToPrimitive ( input [ , PreferredType ] )
-void ConversionBuiltinsAssembler::Generate_NonPrimitiveToPrimitive(
- TNode<Context> context, TNode<Object> input, ToPrimitiveHint hint) {
- // Lookup the @@toPrimitive property on the {input}.
- TNode<Object> exotic_to_prim =
- GetProperty(context, input, factory()->to_primitive_symbol());
-
- // Check if {exotic_to_prim} is neither null nor undefined.
- Label ordinary_to_primitive(this);
- GotoIf(IsNullOrUndefined(exotic_to_prim), &ordinary_to_primitive);
- {
- // Invoke the {exotic_to_prim} method on the {input} with a string
- // representation of the {hint}.
- TNode<String> hint_string =
- HeapConstant(factory()->ToPrimitiveHintString(hint));
- TNode<Object> result = Call(context, exotic_to_prim, input, hint_string);
-
- // Verify that the {result} is actually a primitive.
- Label if_resultisprimitive(this),
- if_resultisnotprimitive(this, Label::kDeferred);
- GotoIf(TaggedIsSmi(result), &if_resultisprimitive);
- TNode<Uint16T> result_instance_type = LoadInstanceType(CAST(result));
- Branch(IsPrimitiveInstanceType(result_instance_type), &if_resultisprimitive,
- &if_resultisnotprimitive);
-
- BIND(&if_resultisprimitive);
- {
- // Just return the {result}.
- Return(result);
- }
-
- BIND(&if_resultisnotprimitive);
- {
- // Somehow the @@toPrimitive method on {input} didn't yield a primitive.
- ThrowTypeError(context, MessageTemplate::kCannotConvertToPrimitive);
- }
- }
-
- // Convert using the OrdinaryToPrimitive algorithm instead.
- BIND(&ordinary_to_primitive);
- {
- Callable callable = CodeFactory::OrdinaryToPrimitive(
- isolate(), (hint == ToPrimitiveHint::kString)
- ? OrdinaryToPrimitiveHint::kString
- : OrdinaryToPrimitiveHint::kNumber);
- TailCallStub(callable, context, input);
- }
-}
-
-TF_BUILTIN(NonPrimitiveToPrimitive_Default, ConversionBuiltinsAssembler) {
- TNode<Context> context = CAST(Parameter(Descriptor::kContext));
- TNode<Object> input = CAST(Parameter(Descriptor::kArgument));
-
- Generate_NonPrimitiveToPrimitive(context, input, ToPrimitiveHint::kDefault);
-}
-
-TF_BUILTIN(NonPrimitiveToPrimitive_Number, ConversionBuiltinsAssembler) {
- TNode<Context> context = CAST(Parameter(Descriptor::kContext));
- TNode<Object> input = CAST(Parameter(Descriptor::kArgument));
-
- Generate_NonPrimitiveToPrimitive(context, input, ToPrimitiveHint::kNumber);
-}
-
-TF_BUILTIN(NonPrimitiveToPrimitive_String, ConversionBuiltinsAssembler) {
- TNode<Context> context = CAST(Parameter(Descriptor::kContext));
- TNode<Object> input = CAST(Parameter(Descriptor::kArgument));
-
- Generate_NonPrimitiveToPrimitive(context, input, ToPrimitiveHint::kString);
-}
-
-TF_BUILTIN(StringToNumber, CodeStubAssembler) {
- TNode<String> input = CAST(Parameter(Descriptor::kArgument));
-
- Return(StringToNumber(input));
-}
-
-TF_BUILTIN(ToName, CodeStubAssembler) {
- TNode<Context> context = CAST(Parameter(Descriptor::kContext));
- TNode<Object> input = CAST(Parameter(Descriptor::kArgument));
-
- TVARIABLE(Object, var_input, input);
- Label loop(this, &var_input);
- Goto(&loop);
- BIND(&loop);
- {
- // Load the current {input} value.
- TNode<Object> input = var_input.value();
-
- // Dispatch based on the type of the {input.}
- Label if_inputisbigint(this), if_inputisname(this), if_inputisnumber(this),
- if_inputisoddball(this), if_inputisreceiver(this, Label::kDeferred);
- GotoIf(TaggedIsSmi(input), &if_inputisnumber);
- TNode<Uint16T> input_instance_type = LoadInstanceType(CAST(input));
- STATIC_ASSERT(FIRST_NAME_TYPE == FIRST_TYPE);
- GotoIf(IsNameInstanceType(input_instance_type), &if_inputisname);
- GotoIf(IsJSReceiverInstanceType(input_instance_type), &if_inputisreceiver);
- GotoIf(IsHeapNumberInstanceType(input_instance_type), &if_inputisnumber);
- Branch(IsBigIntInstanceType(input_instance_type), &if_inputisbigint,
- &if_inputisoddball);
-
- BIND(&if_inputisbigint);
- {
- // We don't have a fast-path for BigInt currently, so just
- // tail call to the %ToString runtime function here for now.
- TailCallRuntime(Runtime::kToStringRT, context, input);
- }
-
- BIND(&if_inputisname);
- {
- // The {input} is already a Name.
- Return(input);
- }
-
- BIND(&if_inputisnumber);
- {
- // Convert the String {input} to a Number.
- TailCallBuiltin(Builtins::kNumberToString, context, input);
- }
-
- BIND(&if_inputisoddball);
- {
- // Just return the {input}'s string representation.
- CSA_ASSERT(this, IsOddballInstanceType(input_instance_type));
- Return(LoadObjectField(CAST(input), Oddball::kToStringOffset));
- }
-
- BIND(&if_inputisreceiver);
- {
- // Convert the JSReceiver {input} to a primitive first,
- // and then run the loop again with the new {input},
- // which is then a primitive value.
- var_input = CallBuiltin(Builtins::kNonPrimitiveToPrimitive_String,
- context, input);
- Goto(&loop);
- }
- }
-}
-
-TF_BUILTIN(NonNumberToNumber, CodeStubAssembler) {
- TNode<Context> context = CAST(Parameter(Descriptor::kContext));
- TNode<HeapObject> input = CAST(Parameter(Descriptor::kArgument));
-
- Return(NonNumberToNumber(context, input));
-}
-
-TF_BUILTIN(NonNumberToNumeric, CodeStubAssembler) {
- TNode<Context> context = CAST(Parameter(Descriptor::kContext));
- TNode<HeapObject> input = CAST(Parameter(Descriptor::kArgument));
-
- Return(NonNumberToNumeric(context, input));
-}
-
-TF_BUILTIN(ToNumeric, CodeStubAssembler) {
- TNode<Context> context = CAST(Parameter(Descriptor::kContext));
- TNode<Object> input = CAST(Parameter(Descriptor::kArgument));
-
- Return(Select<Numeric>(
- IsNumber(input), [=] { return CAST(input); },
- [=] { return NonNumberToNumeric(context, CAST(input)); }));
-}
-
// ES6 section 7.1.3 ToNumber ( argument )
TF_BUILTIN(ToNumber, CodeStubAssembler) {
// TODO(solanes, v8:6949): Changing this to a TNode<Context> crashes with the
@@ -206,93 +31,6 @@ TF_BUILTIN(ToNumberConvertBigInt, CodeStubAssembler) {
Return(ToNumber(context, input, BigIntHandling::kConvertToNumber));
}
-// ES section #sec-tostring-applied-to-the-number-type
-TF_BUILTIN(NumberToString, CodeStubAssembler) {
- TNode<Number> input = CAST(Parameter(Descriptor::kArgument));
-
- Return(NumberToString(input));
-}
-
-// 7.1.1.1 OrdinaryToPrimitive ( O, hint )
-void ConversionBuiltinsAssembler::Generate_OrdinaryToPrimitive(
- TNode<Context> context, TNode<Object> input, OrdinaryToPrimitiveHint hint) {
- TVARIABLE(Object, var_result);
- Label return_result(this, &var_result);
-
- Handle<String> method_names[2];
- switch (hint) {
- case OrdinaryToPrimitiveHint::kNumber:
- method_names[0] = factory()->valueOf_string();
- method_names[1] = factory()->toString_string();
- break;
- case OrdinaryToPrimitiveHint::kString:
- method_names[0] = factory()->toString_string();
- method_names[1] = factory()->valueOf_string();
- break;
- }
- for (Handle<String> name : method_names) {
- // Lookup the {name} on the {input}.
- TNode<Object> method = GetProperty(context, input, name);
-
- // Check if the {method} is callable.
- Label if_methodiscallable(this),
- if_methodisnotcallable(this, Label::kDeferred);
- GotoIf(TaggedIsSmi(method), &if_methodisnotcallable);
- TNode<Map> method_map = LoadMap(CAST(method));
- Branch(IsCallableMap(method_map), &if_methodiscallable,
- &if_methodisnotcallable);
-
- BIND(&if_methodiscallable);
- {
- // Call the {method} on the {input}.
- TNode<Object> result = Call(context, method, input);
- var_result = result;
-
- // Return the {result} if it is a primitive.
- GotoIf(TaggedIsSmi(result), &return_result);
- TNode<Uint16T> result_instance_type = LoadInstanceType(CAST(result));
- GotoIf(IsPrimitiveInstanceType(result_instance_type), &return_result);
- }
-
- // Just continue with the next {name} if the {method} is not callable.
- Goto(&if_methodisnotcallable);
- BIND(&if_methodisnotcallable);
- }
-
- ThrowTypeError(context, MessageTemplate::kCannotConvertToPrimitive);
-
- BIND(&return_result);
- Return(var_result.value());
-}
-
-TF_BUILTIN(OrdinaryToPrimitive_Number, ConversionBuiltinsAssembler) {
- TNode<Context> context = CAST(Parameter(Descriptor::kContext));
- TNode<Object> input = CAST(Parameter(Descriptor::kArgument));
- Generate_OrdinaryToPrimitive(context, input,
- OrdinaryToPrimitiveHint::kNumber);
-}
-
-TF_BUILTIN(OrdinaryToPrimitive_String, ConversionBuiltinsAssembler) {
- TNode<Context> context = CAST(Parameter(Descriptor::kContext));
- TNode<Object> input = CAST(Parameter(Descriptor::kArgument));
- Generate_OrdinaryToPrimitive(context, input,
- OrdinaryToPrimitiveHint::kString);
-}
-
-// ES6 section 7.1.2 ToBoolean ( argument )
-TF_BUILTIN(ToBoolean, CodeStubAssembler) {
- TNode<Object> value = CAST(Parameter(Descriptor::kArgument));
-
- Label return_true(this), return_false(this);
- BranchIfToBooleanIsTrue(value, &return_true, &return_false);
-
- BIND(&return_true);
- Return(TrueConstant());
-
- BIND(&return_false);
- Return(FalseConstant());
-}
-
// ES6 section 7.1.2 ToBoolean ( argument )
// Requires parameter on stack so that it can be used as a continuation from a
// LAZY deopt.
@@ -309,130 +47,6 @@ TF_BUILTIN(ToBooleanLazyDeoptContinuation, CodeStubAssembler) {
Return(FalseConstant());
}
-TF_BUILTIN(ToLength, CodeStubAssembler) {
- TNode<Context> context = CAST(Parameter(Descriptor::kContext));
-
- // We might need to loop once for ToNumber conversion.
- TVARIABLE(Object, var_len, CAST(Parameter(Descriptor::kArgument)));
- Label loop(this, &var_len);
- Goto(&loop);
- BIND(&loop);
- {
- // Shared entry points.
- Label return_len(this), return_two53minus1(this, Label::kDeferred),
- return_zero(this, Label::kDeferred);
-
- // Load the current {len} value.
- TNode<Object> len = var_len.value();
-
- // Check if {len} is a positive Smi.
- GotoIf(TaggedIsPositiveSmi(len), &return_len);
-
- // Check if {len} is a (negative) Smi.
- GotoIf(TaggedIsSmi(len), &return_zero);
-
- // Check if {len} is a HeapNumber.
- TNode<HeapObject> len_heap_object = CAST(len);
- Label if_lenisheapnumber(this),
- if_lenisnotheapnumber(this, Label::kDeferred);
- Branch(IsHeapNumber(len_heap_object), &if_lenisheapnumber,
- &if_lenisnotheapnumber);
-
- BIND(&if_lenisheapnumber);
- {
- // Load the floating-point value of {len}.
- TNode<Float64T> len_value = LoadHeapNumberValue(len_heap_object);
-
- // Check if {len} is not greater than zero.
- GotoIfNot(Float64GreaterThan(len_value, Float64Constant(0.0)),
- &return_zero);
-
- // Check if {len} is greater than or equal to 2^53-1.
- GotoIf(Float64GreaterThanOrEqual(len_value,
- Float64Constant(kMaxSafeInteger)),
- &return_two53minus1);
-
- // Round the {len} towards -Infinity.
- TNode<Float64T> value = Float64Floor(len_value);
- TNode<Number> result = ChangeFloat64ToTagged(value);
- Return(result);
- }
-
- BIND(&if_lenisnotheapnumber);
- {
- // Need to convert {len} to a Number first.
- var_len = CallBuiltin(Builtins::kNonNumberToNumber, context, len);
- Goto(&loop);
- }
-
- BIND(&return_len);
- Return(var_len.value());
-
- BIND(&return_two53minus1);
- Return(NumberConstant(kMaxSafeInteger));
-
- BIND(&return_zero);
- Return(SmiConstant(0));
- }
-}
-
-// ES6 section 7.1.13 ToObject (argument)
-TF_BUILTIN(ToObject, CodeStubAssembler) {
- Label if_smi(this, Label::kDeferred), if_jsreceiver(this),
- if_noconstructor(this, Label::kDeferred),
- if_wrapjs_primitive_wrapper(this);
-
- TNode<Context> context = CAST(Parameter(Descriptor::kContext));
- TNode<Object> object = CAST(Parameter(Descriptor::kArgument));
-
- TVARIABLE(IntPtrT, constructor_function_index_var);
-
- GotoIf(TaggedIsSmi(object), &if_smi);
-
- TNode<Map> map = LoadMap(CAST(object));
- TNode<Uint16T> instance_type = LoadMapInstanceType(map);
- GotoIf(IsJSReceiverInstanceType(instance_type), &if_jsreceiver);
-
- TNode<IntPtrT> constructor_function_index =
- LoadMapConstructorFunctionIndex(map);
- GotoIf(WordEqual(constructor_function_index,
- IntPtrConstant(Map::kNoConstructorFunctionIndex)),
- &if_noconstructor);
- constructor_function_index_var = constructor_function_index;
- Goto(&if_wrapjs_primitive_wrapper);
-
- BIND(&if_smi);
- constructor_function_index_var =
- IntPtrConstant(Context::NUMBER_FUNCTION_INDEX);
- Goto(&if_wrapjs_primitive_wrapper);
-
- BIND(&if_wrapjs_primitive_wrapper);
- TNode<NativeContext> native_context = LoadNativeContext(context);
- TNode<JSFunction> constructor = CAST(LoadContextElement(
- native_context, constructor_function_index_var.value()));
- TNode<Map> initial_map = LoadObjectField<Map>(
- constructor, JSFunction::kPrototypeOrInitialMapOffset);
- TNode<HeapObject> js_primitive_wrapper =
- Allocate(JSPrimitiveWrapper::kHeaderSize);
- StoreMapNoWriteBarrier(js_primitive_wrapper, initial_map);
- StoreObjectFieldRoot(js_primitive_wrapper,
- JSPrimitiveWrapper::kPropertiesOrHashOffset,
- RootIndex::kEmptyFixedArray);
- StoreObjectFieldRoot(js_primitive_wrapper,
- JSPrimitiveWrapper::kElementsOffset,
- RootIndex::kEmptyFixedArray);
- StoreObjectField(js_primitive_wrapper, JSPrimitiveWrapper::kValueOffset,
- object);
- Return(js_primitive_wrapper);
-
- BIND(&if_noconstructor);
- ThrowTypeError(context, MessageTemplate::kUndefinedOrNullToObject,
- "ToObject");
-
- BIND(&if_jsreceiver);
- Return(object);
-}
-
// ES6 section 12.5.5 typeof operator
TF_BUILTIN(Typeof, CodeStubAssembler) {
TNode<Object> object = CAST(Parameter(Descriptor::kObject));
diff --git a/chromium/v8/src/builtins/builtins-date-gen.cc b/chromium/v8/src/builtins/builtins-date-gen.cc
index a3200330350..05fcc53f12b 100644
--- a/chromium/v8/src/builtins/builtins-date-gen.cc
+++ b/chromium/v8/src/builtins/builtins-date-gen.cc
@@ -197,7 +197,7 @@ TF_BUILTIN(DatePrototypeToPrimitive, CodeStubAssembler) {
hint_is_invalid(this, Label::kDeferred);
// Fast cases for internalized strings.
- TNode<String> number_string = numberStringConstant();
+ TNode<String> number_string = NumberStringConstant();
GotoIf(TaggedEqual(hint, number_string), &hint_is_number);
TNode<String> default_string = DefaultStringConstant();
GotoIf(TaggedEqual(hint, default_string), &hint_is_string);
diff --git a/chromium/v8/src/builtins/builtins-definitions.h b/chromium/v8/src/builtins/builtins-definitions.h
index 84ddf55f6f4..b7286fa5657 100644
--- a/chromium/v8/src/builtins/builtins-definitions.h
+++ b/chromium/v8/src/builtins/builtins-definitions.h
@@ -51,12 +51,19 @@ namespace internal {
ASM(Call_ReceiverIsNullOrUndefined, CallTrampoline) \
ASM(Call_ReceiverIsNotNullOrUndefined, CallTrampoline) \
ASM(Call_ReceiverIsAny, CallTrampoline) \
+ TFC(Call_ReceiverIsNullOrUndefined_WithFeedback, \
+ CallTrampoline_WithFeedback) \
+ TFC(Call_ReceiverIsNotNullOrUndefined_WithFeedback, \
+ CallTrampoline_WithFeedback) \
+ TFC(Call_ReceiverIsAny_WithFeedback, CallTrampoline_WithFeedback) \
\
/* ES6 section 9.5.12[[Call]] ( thisArgument, argumentsList ) */ \
TFC(CallProxy, CallTrampoline) \
ASM(CallVarargs, CallVarargs) \
TFC(CallWithSpread, CallWithSpread) \
+ TFC(CallWithSpread_WithFeedback, CallWithSpread_WithFeedback) \
TFC(CallWithArrayLike, CallWithArrayLike) \
+ TFC(CallWithArrayLike_WithFeedback, CallWithArrayLike_WithFeedback) \
ASM(CallForwardVarargs, CallForwardVarargs) \
ASM(CallFunctionForwardVarargs, CallForwardVarargs) \
/* Call an API callback via a {FunctionTemplateInfo}, doing appropriate */ \
@@ -76,15 +83,20 @@ namespace internal {
ASM(Construct, JSTrampoline) \
ASM(ConstructVarargs, ConstructVarargs) \
TFC(ConstructWithSpread, ConstructWithSpread) \
+ TFC(ConstructWithSpread_WithFeedback, ConstructWithSpread_WithFeedback) \
TFC(ConstructWithArrayLike, ConstructWithArrayLike) \
+ TFC(ConstructWithArrayLike_WithFeedback, \
+ ConstructWithArrayLike_WithFeedback) \
ASM(ConstructForwardVarargs, ConstructForwardVarargs) \
ASM(ConstructFunctionForwardVarargs, ConstructForwardVarargs) \
+ TFC(Construct_WithFeedback, Construct_WithFeedback) \
ASM(JSConstructStubGeneric, Dummy) \
ASM(JSBuiltinsConstructStub, Dummy) \
TFC(FastNewObject, FastNewObject) \
TFS(FastNewClosure, kSharedFunctionInfo, kFeedbackCell) \
TFC(FastNewFunctionContextEval, FastNewFunctionContext) \
TFC(FastNewFunctionContextFunction, FastNewFunctionContext) \
+ TFS(CreateEmptyLiteralObject) \
TFS(CreateRegExpLiteral, kFeedbackVector, kSlot, kPattern, kFlags) \
TFS(CreateEmptyArrayLiteral, kFeedbackVector, kSlot) \
TFS(CreateShallowArrayLiteral, kFeedbackVector, kSlot, kConstantElements) \
@@ -185,22 +197,8 @@ namespace internal {
ASM(HandleDebuggerStatement, ContextOnly) \
\
/* Type conversions */ \
- TFC(ToObject, TypeConversion) \
- TFC(ToBoolean, TypeConversion) \
- TFC(OrdinaryToPrimitive_Number, TypeConversion) \
- TFC(OrdinaryToPrimitive_String, TypeConversion) \
- TFC(NonPrimitiveToPrimitive_Default, TypeConversion) \
- TFC(NonPrimitiveToPrimitive_Number, TypeConversion) \
- TFC(NonPrimitiveToPrimitive_String, TypeConversion) \
- TFC(StringToNumber, TypeConversion) \
- TFC(ToName, TypeConversion) \
- TFC(NonNumberToNumber, TypeConversion) \
- TFC(NonNumberToNumeric, TypeConversion) \
TFC(ToNumber, TypeConversion) \
TFC(ToNumberConvertBigInt, TypeConversion) \
- TFC(ToNumeric, TypeConversion) \
- TFC(NumberToString, TypeConversion) \
- TFC(ToLength, TypeConversion) \
TFC(Typeof, Typeof) \
TFC(GetSuperConstructor, Typeof) \
TFC(BigIntToI64, BigIntToI64) \
@@ -503,11 +501,7 @@ namespace internal {
CPP(FunctionConstructor) \
ASM(FunctionPrototypeApply, JSTrampoline) \
CPP(FunctionPrototypeBind) \
- /* ES6 #sec-function.prototype.bind */ \
- TFJ(FastFunctionPrototypeBind, kDontAdaptArgumentsSentinel) \
ASM(FunctionPrototypeCall, JSTrampoline) \
- /* ES6 #sec-function.prototype-@@hasinstance */ \
- TFJ(FunctionPrototypeHasInstance, 1, kReceiver, kV) \
/* ES6 #sec-function.prototype.tostring */ \
CPP(FunctionPrototypeToString) \
\
@@ -605,53 +599,42 @@ namespace internal {
TFJ(MapIteratorPrototypeNext, 0, kReceiver) \
TFS(MapIteratorToList, kSource) \
\
- /* Number */ \
- TFC(AllocateHeapNumber, AllocateHeapNumber) \
/* ES #sec-number-constructor */ \
TFJ(NumberConstructor, kDontAdaptArgumentsSentinel) \
- /* ES6 #sec-number.isfinite */ \
- TFJ(NumberIsFinite, 1, kReceiver, kNumber) \
- /* ES6 #sec-number.isinteger */ \
- TFJ(NumberIsInteger, 1, kReceiver, kNumber) \
- /* ES6 #sec-number.isnan */ \
- TFJ(NumberIsNaN, 1, kReceiver, kNumber) \
- /* ES6 #sec-number.issafeinteger */ \
- TFJ(NumberIsSafeInteger, 1, kReceiver, kNumber) \
- /* ES6 #sec-number.parsefloat */ \
- TFJ(NumberParseFloat, 1, kReceiver, kString) \
- /* ES6 #sec-number.parseint */ \
- TFJ(NumberParseInt, 2, kReceiver, kString, kRadix) \
- TFS(ParseInt, kString, kRadix) \
CPP(NumberPrototypeToExponential) \
CPP(NumberPrototypeToFixed) \
CPP(NumberPrototypeToLocaleString) \
CPP(NumberPrototypeToPrecision) \
- /* ES6 #sec-number.prototype.valueof */ \
- TFJ(NumberPrototypeValueOf, 0, kReceiver) \
- TFC(Add, BinaryOp) \
- TFC(Subtract, BinaryOp) \
- TFC(Multiply, BinaryOp) \
- TFC(Divide, BinaryOp) \
- TFC(Modulus, BinaryOp) \
- TFC(Exponentiate, BinaryOp) \
- TFC(BitwiseAnd, BinaryOp) \
- TFC(BitwiseOr, BinaryOp) \
- TFC(BitwiseXor, BinaryOp) \
- TFC(ShiftLeft, BinaryOp) \
- TFC(ShiftRight, BinaryOp) \
- TFC(ShiftRightLogical, BinaryOp) \
- TFC(LessThan, Compare) \
- TFC(LessThanOrEqual, Compare) \
- TFC(GreaterThan, Compare) \
- TFC(GreaterThanOrEqual, Compare) \
- TFC(Equal, Compare) \
TFC(SameValue, Compare) \
TFC(SameValueNumbersOnly, Compare) \
- TFC(StrictEqual, Compare) \
- TFS(BitwiseNot, kValue) \
- TFS(Decrement, kValue) \
- TFS(Increment, kValue) \
- TFS(Negate, kValue) \
+ \
+ /* Binary ops with feedback collection */ \
+ TFC(Add_WithFeedback, BinaryOp_WithFeedback) \
+ TFC(Subtract_WithFeedback, BinaryOp_WithFeedback) \
+ TFC(Multiply_WithFeedback, BinaryOp_WithFeedback) \
+ TFC(Divide_WithFeedback, BinaryOp_WithFeedback) \
+ TFC(Modulus_WithFeedback, BinaryOp_WithFeedback) \
+ TFC(Exponentiate_WithFeedback, BinaryOp_WithFeedback) \
+ TFC(BitwiseAnd_WithFeedback, BinaryOp_WithFeedback) \
+ TFC(BitwiseOr_WithFeedback, BinaryOp_WithFeedback) \
+ TFC(BitwiseXor_WithFeedback, BinaryOp_WithFeedback) \
+ TFC(ShiftLeft_WithFeedback, BinaryOp_WithFeedback) \
+ TFC(ShiftRight_WithFeedback, BinaryOp_WithFeedback) \
+ TFC(ShiftRightLogical_WithFeedback, BinaryOp_WithFeedback) \
+ \
+ /* Compare ops with feedback collection */ \
+ TFC(Equal_WithFeedback, Compare_WithFeedback) \
+ TFC(StrictEqual_WithFeedback, Compare_WithFeedback) \
+ TFC(LessThan_WithFeedback, Compare_WithFeedback) \
+ TFC(GreaterThan_WithFeedback, Compare_WithFeedback) \
+ TFC(LessThanOrEqual_WithFeedback, Compare_WithFeedback) \
+ TFC(GreaterThanOrEqual_WithFeedback, Compare_WithFeedback) \
+ \
+ /* Unary ops with feedback collection */ \
+ TFC(BitwiseNot_WithFeedback, UnaryOp_WithFeedback) \
+ TFC(Decrement_WithFeedback, UnaryOp_WithFeedback) \
+ TFC(Increment_WithFeedback, UnaryOp_WithFeedback) \
+ TFC(Negate_WithFeedback, UnaryOp_WithFeedback) \
\
/* Object */ \
/* ES #sec-object-constructor */ \
@@ -813,12 +796,6 @@ namespace internal {
TFJ(TypedArrayPrototypeByteOffset, 0, kReceiver) \
/* ES6 #sec-get-%typedarray%.prototype.length */ \
TFJ(TypedArrayPrototypeLength, 0, kReceiver) \
- /* ES6 #sec-%typedarray%.prototype.entries */ \
- TFJ(TypedArrayPrototypeEntries, 0, kReceiver) \
- /* ES6 #sec-%typedarray%.prototype.keys */ \
- TFJ(TypedArrayPrototypeKeys, 0, kReceiver) \
- /* ES6 #sec-%typedarray%.prototype.values */ \
- TFJ(TypedArrayPrototypeValues, 0, kReceiver) \
/* ES6 #sec-%typedarray%.prototype.copywithin */ \
CPP(TypedArrayPrototypeCopyWithin) \
/* ES6 #sec-%typedarray%.prototype.fill */ \
@@ -842,14 +819,8 @@ namespace internal {
TFC(WasmFloat32ToNumber, WasmFloat32ToNumber) \
TFC(WasmFloat64ToNumber, WasmFloat64ToNumber) \
TFS(WasmAllocateArray, kMapIndex, kLength, kElementSize) \
- TFS(WasmAllocateStruct, kMapIndex) \
- TFC(WasmAtomicNotify, WasmAtomicNotify) \
TFC(WasmI32AtomicWait32, WasmI32AtomicWait32) \
- TFC(WasmI32AtomicWait64, WasmI32AtomicWait64) \
TFC(WasmI64AtomicWait32, WasmI64AtomicWait32) \
- TFC(WasmI64AtomicWait64, WasmI64AtomicWait64) \
- TFC(WasmTableInit, WasmTableInit) \
- TFC(WasmTableCopy, WasmTableCopy) \
\
/* WeakMap */ \
TFJ(WeakMapConstructor, kDontAdaptArgumentsSentinel) \
@@ -906,11 +877,11 @@ namespace internal {
/* %AsyncFromSyncIteratorPrototype% */ \
/* See tc39.github.io/proposal-async-iteration/ */ \
/* #sec-%asyncfromsynciteratorprototype%-object) */ \
- TFJ(AsyncFromSyncIteratorPrototypeNext, 1, kReceiver, kValue) \
+ TFJ(AsyncFromSyncIteratorPrototypeNext, kDontAdaptArgumentsSentinel) \
/* #sec-%asyncfromsynciteratorprototype%.throw */ \
- TFJ(AsyncFromSyncIteratorPrototypeThrow, 1, kReceiver, kReason) \
+ TFJ(AsyncFromSyncIteratorPrototypeThrow, kDontAdaptArgumentsSentinel) \
/* #sec-%asyncfromsynciteratorprototype%.return */ \
- TFJ(AsyncFromSyncIteratorPrototypeReturn, 1, kReceiver, kValue) \
+ TFJ(AsyncFromSyncIteratorPrototypeReturn, kDontAdaptArgumentsSentinel) \
/* #sec-async-iterator-value-unwrap-functions */ \
TFJ(AsyncIteratorValueUnwrap, 1, kReceiver, kValue) \
\
diff --git a/chromium/v8/src/builtins/builtins-descriptors.h b/chromium/v8/src/builtins/builtins-descriptors.h
index 174b89795f5..c2eb44debea 100644
--- a/chromium/v8/src/builtins/builtins-descriptors.h
+++ b/chromium/v8/src/builtins/builtins-descriptors.h
@@ -13,34 +13,7 @@
namespace v8 {
namespace internal {
-#define REVERSE_0(a) a,
-#define REVERSE_1(a, b) b, a,
-#define REVERSE_2(a, b, c) c, b, a,
-#define REVERSE_3(a, b, c, d) d, c, b, a,
-#define REVERSE_4(a, b, c, d, e) e, d, c, b, a,
-#define REVERSE_5(a, b, c, d, e, f) f, e, d, c, b, a,
-#define REVERSE_6(a, b, c, d, e, f, g) g, f, e, d, c, b, a,
-#define REVERSE_7(a, b, c, d, e, f, g, h) h, g, f, e, d, c, b, a,
-#define REVERSE_8(a, b, c, d, e, f, g, h, i) i, h, g, f, e, d, c, b, a,
-#define REVERSE_kDontAdaptArgumentsSentinel(...)
-#define REVERSE(N, ...) REVERSE_##N(__VA_ARGS__)
-
// Define interface descriptors for builtins with JS linkage.
-#ifdef V8_REVERSE_JSARGS
-#define DEFINE_TFJ_INTERFACE_DESCRIPTOR(Name, Argc, ...) \
- struct Builtin_##Name##_InterfaceDescriptor { \
- enum ParameterIndices { \
- kJSTarget = compiler::CodeAssembler::kTargetParameterIndex, \
- REVERSE_##Argc(__VA_ARGS__) kJSNewTarget, \
- kJSActualArgumentsCount, \
- kContext, \
- kParameterCount, \
- }; \
- static_assert((Argc) == static_cast<uint16_t>(kParameterCount - 4), \
- "Inconsistent set of arguments"); \
- static_assert(kJSTarget == -1, "Unexpected kJSTarget index value"); \
- };
-#else
#define DEFINE_TFJ_INTERFACE_DESCRIPTOR(Name, Argc, ...) \
struct Builtin_##Name##_InterfaceDescriptor { \
enum ParameterIndices { \
@@ -55,7 +28,6 @@ namespace internal {
"Inconsistent set of arguments"); \
static_assert(kJSTarget == -1, "Unexpected kJSTarget index value"); \
};
-#endif
// Define interface descriptors for builtins with StubCall linkage.
#define DEFINE_TFC_INTERFACE_DESCRIPTOR(Name, InterfaceDescriptor) \
diff --git a/chromium/v8/src/builtins/builtins-function-gen.cc b/chromium/v8/src/builtins/builtins-function-gen.cc
deleted file mode 100644
index 1d48ee84d1c..00000000000
--- a/chromium/v8/src/builtins/builtins-function-gen.cc
+++ /dev/null
@@ -1,202 +0,0 @@
-// Copyright 2017 the V8 project authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "src/builtins/builtins-utils-gen.h"
-#include "src/builtins/builtins.h"
-#include "src/codegen/code-stub-assembler.h"
-#include "src/execution/frame-constants.h"
-#include "src/objects/api-callbacks.h"
-#include "src/objects/descriptor-array.h"
-
-namespace v8 {
-namespace internal {
-
-TF_BUILTIN(FastFunctionPrototypeBind, CodeStubAssembler) {
- Label slow(this);
-
- TNode<Int32T> argc =
- UncheckedCast<Int32T>(Parameter(Descriptor::kJSActualArgumentsCount));
- TNode<Context> context = CAST(Parameter(Descriptor::kContext));
- TNode<Object> new_target = CAST(Parameter(Descriptor::kJSNewTarget));
-
- CodeStubArguments args(this, argc);
-
- // Check that receiver has instance type of JS_FUNCTION_TYPE
- TNode<Object> receiver = args.GetReceiver();
- GotoIf(TaggedIsSmi(receiver), &slow);
-
- TNode<Map> receiver_map = LoadMap(CAST(receiver));
- {
- TNode<Uint16T> instance_type = LoadMapInstanceType(receiver_map);
- GotoIfNot(
- Word32Or(InstanceTypeEqual(instance_type, JS_FUNCTION_TYPE),
- InstanceTypeEqual(instance_type, JS_BOUND_FUNCTION_TYPE)),
- &slow);
- }
-
- // Disallow binding of slow-mode functions. We need to figure out whether the
- // length and name property are in the original state.
- Comment("Disallow binding of slow-mode functions");
- GotoIf(IsDictionaryMap(receiver_map), &slow);
-
- // Check whether the length and name properties are still present as
- // AccessorInfo objects. In that case, their value can be recomputed even if
- // the actual value on the object changes.
- Comment("Check descriptor array length");
- // Minimum descriptor array length required for fast path.
- const int min_nof_descriptors = i::Max(JSFunction::kLengthDescriptorIndex,
- JSFunction::kNameDescriptorIndex) +
- 1;
- TNode<Int32T> nof_descriptors = LoadNumberOfOwnDescriptors(receiver_map);
- GotoIf(Int32LessThan(nof_descriptors, Int32Constant(min_nof_descriptors)),
- &slow);
-
- // Check whether the length and name properties are still present as
- // AccessorInfo objects. In that case, their value can be recomputed even if
- // the actual value on the object changes.
- Comment("Check name and length properties");
- {
- TNode<DescriptorArray> descriptors = LoadMapDescriptors(receiver_map);
- const int length_index = JSFunction::kLengthDescriptorIndex;
- TNode<Name> maybe_length =
- LoadKeyByDescriptorEntry(descriptors, length_index);
- GotoIf(TaggedNotEqual(maybe_length, LengthStringConstant()), &slow);
-
- TNode<Object> maybe_length_accessor =
- LoadValueByDescriptorEntry(descriptors, length_index);
- GotoIf(TaggedIsSmi(maybe_length_accessor), &slow);
- TNode<Map> length_value_map = LoadMap(CAST(maybe_length_accessor));
- GotoIfNot(IsAccessorInfoMap(length_value_map), &slow);
-
- const int name_index = JSFunction::kNameDescriptorIndex;
- TNode<Name> maybe_name = LoadKeyByDescriptorEntry(descriptors, name_index);
- GotoIf(TaggedNotEqual(maybe_name, NameStringConstant()), &slow);
-
- TNode<Object> maybe_name_accessor =
- LoadValueByDescriptorEntry(descriptors, name_index);
- GotoIf(TaggedIsSmi(maybe_name_accessor), &slow);
- TNode<Map> name_value_map = LoadMap(CAST(maybe_name_accessor));
- GotoIfNot(IsAccessorInfoMap(name_value_map), &slow);
- }
-
- // Choose the right bound function map based on whether the target is
- // constructable.
- Comment("Choose the right bound function map");
- TVARIABLE(Map, bound_function_map);
- {
- Label with_constructor(this);
- TNode<NativeContext> native_context = LoadNativeContext(context);
-
- Label map_done(this, &bound_function_map);
- GotoIf(IsConstructorMap(receiver_map), &with_constructor);
-
- bound_function_map = CAST(LoadContextElement(
- native_context, Context::BOUND_FUNCTION_WITHOUT_CONSTRUCTOR_MAP_INDEX));
- Goto(&map_done);
-
- BIND(&with_constructor);
- bound_function_map = CAST(LoadContextElement(
- native_context, Context::BOUND_FUNCTION_WITH_CONSTRUCTOR_MAP_INDEX));
- Goto(&map_done);
-
- BIND(&map_done);
- }
-
- // Verify that __proto__ matches that of a the target bound function.
- Comment("Verify that __proto__ matches target bound function");
- TNode<HeapObject> prototype = LoadMapPrototype(receiver_map);
- TNode<HeapObject> expected_prototype =
- LoadMapPrototype(bound_function_map.value());
- GotoIf(TaggedNotEqual(prototype, expected_prototype), &slow);
-
- // Allocate the arguments array.
- Comment("Allocate the arguments array");
- TVARIABLE(FixedArray, argument_array);
- {
- Label empty_arguments(this);
- Label arguments_done(this, &argument_array);
- GotoIf(Uint32LessThanOrEqual(argc, Int32Constant(1)), &empty_arguments);
- TNode<IntPtrT> elements_length =
- Signed(ChangeUint32ToWord(Unsigned(Int32Sub(argc, Int32Constant(1)))));
- argument_array = CAST(AllocateFixedArray(PACKED_ELEMENTS, elements_length,
- kAllowLargeObjectAllocation));
- TVARIABLE(IntPtrT, index, IntPtrConstant(0));
- VariableList foreach_vars({&index}, zone());
- args.ForEach(
- foreach_vars,
- [&](TNode<Object> arg) {
- StoreFixedArrayElement(argument_array.value(), index.value(), arg);
- Increment(&index);
- },
- IntPtrConstant(1));
- Goto(&arguments_done);
-
- BIND(&empty_arguments);
- argument_array = EmptyFixedArrayConstant();
- Goto(&arguments_done);
-
- BIND(&arguments_done);
- }
-
- // Determine bound receiver.
- Comment("Determine bound receiver");
- TVARIABLE(Object, bound_receiver);
- {
- Label has_receiver(this);
- Label receiver_done(this, &bound_receiver);
- GotoIf(Word32NotEqual(argc, Int32Constant(0)), &has_receiver);
- bound_receiver = UndefinedConstant();
- Goto(&receiver_done);
-
- BIND(&has_receiver);
- bound_receiver = args.AtIndex(0);
- Goto(&receiver_done);
-
- BIND(&receiver_done);
- }
-
- // Allocate the resulting bound function.
- Comment("Allocate the resulting bound function");
- {
- TNode<HeapObject> bound_function = Allocate(JSBoundFunction::kHeaderSize);
- StoreMapNoWriteBarrier(bound_function, bound_function_map.value());
- StoreObjectFieldNoWriteBarrier(
- bound_function, JSBoundFunction::kBoundTargetFunctionOffset, receiver);
- StoreObjectFieldNoWriteBarrier(bound_function,
- JSBoundFunction::kBoundThisOffset,
- bound_receiver.value());
- StoreObjectFieldNoWriteBarrier(bound_function,
- JSBoundFunction::kBoundArgumentsOffset,
- argument_array.value());
- TNode<FixedArray> empty_fixed_array = EmptyFixedArrayConstant();
- StoreObjectFieldNoWriteBarrier(
- bound_function, JSObject::kPropertiesOrHashOffset, empty_fixed_array);
- StoreObjectFieldNoWriteBarrier(bound_function, JSObject::kElementsOffset,
- empty_fixed_array);
-
- args.PopAndReturn(bound_function);
- }
-
- BIND(&slow);
- {
- // We are not using Parameter(Descriptor::kJSTarget) and loading the value
- // from the current frame here in order to reduce register pressure on the
- // fast path.
- TNode<JSFunction> target = LoadTargetFromFrame();
- TailCallBuiltin(Builtins::kFunctionPrototypeBind, context, target,
- new_target, argc);
- }
-}
-
-// ES6 #sec-function.prototype-@@hasinstance
-TF_BUILTIN(FunctionPrototypeHasInstance, CodeStubAssembler) {
- TNode<Context> context = CAST(Parameter(Descriptor::kContext));
- TNode<Object> f = CAST(Parameter(Descriptor::kReceiver));
- TNode<Object> v = CAST(Parameter(Descriptor::kV));
- TNode<Oddball> result = OrdinaryHasInstance(context, f, v);
- Return(result);
-}
-
-} // namespace internal
-} // namespace v8
diff --git a/chromium/v8/src/builtins/builtins-handler-gen.cc b/chromium/v8/src/builtins/builtins-handler-gen.cc
index 0325ddab7c9..3f4a53a3461 100644
--- a/chromium/v8/src/builtins/builtins-handler-gen.cc
+++ b/chromium/v8/src/builtins/builtins-handler-gen.cc
@@ -9,6 +9,7 @@
#include "src/ic/ic.h"
#include "src/ic/keyed-store-generic.h"
#include "src/objects/objects-inl.h"
+#include "torque-generated/exported-macros-assembler-tq.h"
namespace v8 {
namespace internal {
@@ -78,37 +79,11 @@ TNode<Object> HandlerBuiltinsAssembler::EmitKeyedSloppyArguments(
TNode<JSObject> receiver, TNode<Object> tagged_key,
base::Optional<TNode<Object>> value, Label* bailout,
ArgumentsAccessMode access_mode) {
- // Mapped arguments are actual arguments. Unmapped arguments are values added
- // to the arguments object after it was created for the call. Mapped arguments
- // are stored in the context at indexes given by elements[key + 2]. Unmapped
- // arguments are stored as regular indexed properties in the arguments array,
- // held at elements[1]. See NewSloppyArguments() in runtime.cc for a detailed
- // look at argument object construction.
- //
- // The sloppy arguments elements array has a special format:
- //
- // 0: context
- // 1: unmapped arguments array
- // 2: mapped_index0,
- // 3: mapped_index1,
- // ...
- //
- // length is 2 + min(number_of_actual_arguments, number_of_formal_arguments).
- // If key + 2 >= elements.length then attempt to look in the unmapped
- // arguments array (given by elements[1]) and return the value at key, missing
- // to the runtime if the unmapped arguments array is not a fixed array or if
- // key >= unmapped_arguments_array.length.
- //
- // Otherwise, t = elements[key + 2]. If t is the hole, then look up the value
- // in the unmapped arguments array, as described above. Otherwise, t is a Smi
- // index into the context array given at elements[0]. Return the value at
- // context[t].
-
GotoIfNot(TaggedIsSmi(tagged_key), bailout);
TNode<IntPtrT> key = SmiUntag(CAST(tagged_key));
GotoIf(IntPtrLessThan(key, IntPtrConstant(0)), bailout);
- TNode<FixedArray> elements = CAST(LoadElements(receiver));
+ TNode<SloppyArgumentsElements> elements = CAST(LoadElements(receiver));
TNode<IntPtrT> elements_length = LoadAndUntagFixedArrayBaseLength(elements);
TVARIABLE(Object, var_result);
@@ -119,20 +94,18 @@ TNode<Object> HandlerBuiltinsAssembler::EmitKeyedSloppyArguments(
access_mode == ArgumentsAccessMode::kHas);
}
Label if_mapped(this), if_unmapped(this), end(this, &var_result);
- TNode<IntPtrT> intptr_two = IntPtrConstant(2);
- TNode<IntPtrT> adjusted_length = IntPtrSub(elements_length, intptr_two);
- GotoIf(UintPtrGreaterThanOrEqual(key, adjusted_length), &if_unmapped);
+ GotoIf(UintPtrGreaterThanOrEqual(key, elements_length), &if_unmapped);
TNode<Object> mapped_index =
- LoadFixedArrayElement(elements, IntPtrAdd(key, intptr_two));
+ LoadSloppyArgumentsElementsMappedEntries(elements, key);
Branch(TaggedEqual(mapped_index, TheHoleConstant()), &if_unmapped,
&if_mapped);
BIND(&if_mapped);
{
TNode<IntPtrT> mapped_index_intptr = SmiUntag(CAST(mapped_index));
- TNode<Context> the_context = CAST(LoadFixedArrayElement(elements, 0));
+ TNode<Context> the_context = LoadSloppyArgumentsElementsContext(elements);
if (access_mode == ArgumentsAccessMode::kLoad) {
TNode<Object> result =
LoadContextElement(the_context, mapped_index_intptr);
@@ -151,7 +124,7 @@ TNode<Object> HandlerBuiltinsAssembler::EmitKeyedSloppyArguments(
BIND(&if_unmapped);
{
TNode<HeapObject> backing_store_ho =
- CAST(LoadFixedArrayElement(elements, 1));
+ LoadSloppyArgumentsElementsArguments(elements);
GotoIf(TaggedNotEqual(LoadMap(backing_store_ho), FixedArrayMapConstant()),
bailout);
TNode<FixedArray> backing_store = CAST(backing_store_ho);
diff --git a/chromium/v8/src/builtins/builtins-internal-gen.cc b/chromium/v8/src/builtins/builtins-internal-gen.cc
index 61f03b3f993..214f94802f3 100644
--- a/chromium/v8/src/builtins/builtins-internal-gen.cc
+++ b/chromium/v8/src/builtins/builtins-internal-gen.cc
@@ -72,7 +72,7 @@ TF_BUILTIN(GrowFastSmiOrObjectElements, CodeStubAssembler) {
}
TF_BUILTIN(NewArgumentsElements, CodeStubAssembler) {
- TNode<IntPtrT> frame = UncheckedCast<IntPtrT>(Parameter(Descriptor::kFrame));
+ TNode<RawPtrT> frame = UncheckedCast<RawPtrT>(Parameter(Descriptor::kFrame));
TNode<IntPtrT> length = SmiToIntPtr(Parameter(Descriptor::kLength));
TNode<IntPtrT> mapped_count =
SmiToIntPtr(Parameter(Descriptor::kMappedCount));
@@ -127,10 +127,8 @@ TF_BUILTIN(NewArgumentsElements, CodeStubAssembler) {
}
BIND(&done_loop1);
- // Compute the effective {offset} into the {frame}.
- TNode<IntPtrT> offset = IntPtrAdd(length, IntPtrConstant(1));
-
// Copy the parameters from {frame} (starting at {offset}) to {result}.
+ CodeStubArguments args(this, length, frame);
Label loop2(this, &var_index), done_loop2(this);
Goto(&loop2);
BIND(&loop2);
@@ -142,9 +140,7 @@ TF_BUILTIN(NewArgumentsElements, CodeStubAssembler) {
GotoIf(IntPtrEqual(index, length), &done_loop2);
// Load the parameter at the given {index}.
- TNode<Object> value = BitcastWordToTagged(
- Load(MachineType::Pointer(), frame,
- TimesSystemPointerSize(IntPtrSub(offset, index))));
+ TNode<Object> value = args.AtIndex(index);
// Store the {value} into the {result}.
StoreFixedArrayElement(result, index, value, SKIP_WRITE_BARRIER);
@@ -221,9 +217,9 @@ class RecordWriteCodeStubAssembler : public CodeStubAssembler {
TNode<BoolT> IsPageFlagSet(TNode<IntPtrT> object, int mask) {
TNode<IntPtrT> page = PageFromAddress(object);
- TNode<IntPtrT> flags =
- UncheckedCast<IntPtrT>(Load(MachineType::Pointer(), page,
- IntPtrConstant(MemoryChunk::kFlagsOffset)));
+ TNode<IntPtrT> flags = UncheckedCast<IntPtrT>(
+ Load(MachineType::Pointer(), page,
+ IntPtrConstant(BasicMemoryChunk::kFlagsOffset)));
return WordNotEqual(WordAnd(flags, IntPtrConstant(mask)),
IntPtrConstant(0));
}
@@ -242,8 +238,8 @@ class RecordWriteCodeStubAssembler : public CodeStubAssembler {
void GetMarkBit(TNode<IntPtrT> object, TNode<IntPtrT>* cell,
TNode<IntPtrT>* mask) {
TNode<IntPtrT> page = PageFromAddress(object);
- TNode<IntPtrT> bitmap =
- Load<IntPtrT>(page, IntPtrConstant(MemoryChunk::kMarkBitmapOffset));
+ TNode<IntPtrT> bitmap = Load<IntPtrT>(
+ page, IntPtrConstant(BasicMemoryChunk::kMarkBitmapOffset));
{
// Temp variable to calculate cell offset in bitmap.
diff --git a/chromium/v8/src/builtins/builtins-microtask-queue-gen.cc b/chromium/v8/src/builtins/builtins-microtask-queue-gen.cc
index e613ae9c08c..1da6f54c820 100644
--- a/chromium/v8/src/builtins/builtins-microtask-queue-gen.cc
+++ b/chromium/v8/src/builtins/builtins-microtask-queue-gen.cc
@@ -198,11 +198,18 @@ void MicrotaskQueueBuiltinsAssembler::RunSingleMicrotask(
const TNode<Object> thenable = LoadObjectField(
microtask, PromiseResolveThenableJobTask::kThenableOffset);
+ RunPromiseHook(Runtime::kPromiseHookBefore, microtask_context,
+ CAST(promise_to_resolve));
+
{
ScopedExceptionHandler handler(this, &if_exception, &var_exception);
CallBuiltin(Builtins::kPromiseResolveThenableJob, native_context,
promise_to_resolve, thenable, then);
}
+
+ RunPromiseHook(Runtime::kPromiseHookAfter, microtask_context,
+ CAST(promise_to_resolve));
+
RewindEnteredContext(saved_entered_context_count);
SetCurrentContext(current_context);
Goto(&done);
diff --git a/chromium/v8/src/builtins/builtins-number-gen.cc b/chromium/v8/src/builtins/builtins-number-gen.cc
index 4513d73abc7..4e8bcae60be 100644
--- a/chromium/v8/src/builtins/builtins-number-gen.cc
+++ b/chromium/v8/src/builtins/builtins-number-gen.cc
@@ -6,6 +6,7 @@
#include "src/builtins/builtins.h"
#include "src/codegen/code-stub-assembler.h"
#include "src/ic/binary-op-assembler.h"
+#include "src/ic/unary-op-assembler.h"
namespace v8 {
namespace internal {
@@ -13,983 +14,108 @@ namespace internal {
// -----------------------------------------------------------------------------
// ES6 section 20.1 Number Objects
-class NumberBuiltinsAssembler : public CodeStubAssembler {
- public:
- explicit NumberBuiltinsAssembler(compiler::CodeAssemblerState* state)
- : CodeStubAssembler(state) {}
-
- protected:
- template <typename Descriptor>
- void EmitBitwiseOp(Operation op) {
- TNode<Object> left = CAST(Parameter(Descriptor::kLeft));
- TNode<Object> right = CAST(Parameter(Descriptor::kRight));
- TNode<Context> context = CAST(Parameter(Descriptor::kContext));
-
- BinaryOpAssembler binop_asm(state());
- Return(binop_asm.Generate_BitwiseBinaryOp(op, left, right, context));
- }
-
- template <typename Descriptor>
- void RelationalComparisonBuiltin(Operation op) {
- TNode<Object> lhs = CAST(Parameter(Descriptor::kLeft));
- TNode<Object> rhs = CAST(Parameter(Descriptor::kRight));
- TNode<Context> context = CAST(Parameter(Descriptor::kContext));
-
- Return(RelationalComparison(op, lhs, rhs, context));
- }
-
- template <typename Descriptor>
- void UnaryOp(TVariable<Object>* var_input, Label* do_smi, Label* do_double,
- TVariable<Float64T>* var_input_double, Label* do_bigint);
-
- template <typename Descriptor>
- void BinaryOp(Label* smis, TVariable<Object>* var_left,
- TVariable<Object>* var_right, Label* doubles,
- TVariable<Float64T>* var_left_double,
- TVariable<Float64T>* var_right_double, Label* bigints);
-};
-
-// ES6 #sec-number.isfinite
-TF_BUILTIN(NumberIsFinite, CodeStubAssembler) {
- TNode<Object> number = CAST(Parameter(Descriptor::kNumber));
-
- Label return_true(this), return_false(this);
-
- // Check if {number} is a Smi.
- GotoIf(TaggedIsSmi(number), &return_true);
-
- // Check if {number} is a HeapNumber.
- TNode<HeapObject> number_heap_object = CAST(number);
- GotoIfNot(IsHeapNumber(number_heap_object), &return_false);
-
- // Check if {number} contains a finite, non-NaN value.
- TNode<Float64T> number_value = LoadHeapNumberValue(number_heap_object);
- BranchIfFloat64IsNaN(Float64Sub(number_value, number_value), &return_false,
- &return_true);
-
- BIND(&return_true);
- Return(TrueConstant());
-
- BIND(&return_false);
- Return(FalseConstant());
-}
-
-TF_BUILTIN(AllocateHeapNumber, CodeStubAssembler) {
- TNode<HeapNumber> result = AllocateHeapNumber();
- Return(result);
-}
-
-// ES6 #sec-number.isinteger
-TF_BUILTIN(NumberIsInteger, CodeStubAssembler) {
- TNode<Object> number = CAST(Parameter(Descriptor::kNumber));
- Return(SelectBooleanConstant(IsInteger(number)));
-}
-
-// ES6 #sec-number.isnan
-TF_BUILTIN(NumberIsNaN, CodeStubAssembler) {
- TNode<Object> number = CAST(Parameter(Descriptor::kNumber));
-
- Label return_true(this), return_false(this);
-
- // Check if {number} is a Smi.
- GotoIf(TaggedIsSmi(number), &return_false);
-
- // Check if {number} is a HeapNumber.
- TNode<HeapObject> number_heap_object = CAST(number);
- GotoIfNot(IsHeapNumber(number_heap_object), &return_false);
-
- // Check if {number} contains a NaN value.
- TNode<Float64T> number_value = LoadHeapNumberValue(number_heap_object);
- BranchIfFloat64IsNaN(number_value, &return_true, &return_false);
-
- BIND(&return_true);
- Return(TrueConstant());
-
- BIND(&return_false);
- Return(FalseConstant());
-}
-
-// ES6 #sec-number.issafeinteger
-TF_BUILTIN(NumberIsSafeInteger, CodeStubAssembler) {
- TNode<Object> number = CAST(Parameter(Descriptor::kNumber));
- Return(SelectBooleanConstant(IsSafeInteger(number)));
-}
-
-// ES6 #sec-number.parsefloat
-TF_BUILTIN(NumberParseFloat, CodeStubAssembler) {
- TNode<Context> context = CAST(Parameter(Descriptor::kContext));
-
- // We might need to loop once for ToString conversion.
- TVARIABLE(Object, var_input, CAST(Parameter(Descriptor::kString)));
- Label loop(this, &var_input);
- Goto(&loop);
- BIND(&loop);
- {
- // Load the current {input} value.
- TNode<Object> input = var_input.value();
-
- // Check if the {input} is a HeapObject or a Smi.
- Label if_inputissmi(this), if_inputisnotsmi(this);
- Branch(TaggedIsSmi(input), &if_inputissmi, &if_inputisnotsmi);
-
- BIND(&if_inputissmi);
- {
- // The {input} is already a Number, no need to do anything.
- Return(input);
- }
-
- BIND(&if_inputisnotsmi);
- {
- // The {input} is a HeapObject, check if it's already a String.
- TNode<HeapObject> input_heap_object = CAST(input);
- Label if_inputisstring(this), if_inputisnotstring(this);
- TNode<Map> input_map = LoadMap(input_heap_object);
- TNode<Uint16T> input_instance_type = LoadMapInstanceType(input_map);
- Branch(IsStringInstanceType(input_instance_type), &if_inputisstring,
- &if_inputisnotstring);
-
- BIND(&if_inputisstring);
- {
- // The {input} is already a String, check if {input} contains
- // a cached array index.
- Label if_inputcached(this), if_inputnotcached(this);
- TNode<Uint32T> input_hash = LoadNameHashField(CAST(input));
- Branch(IsClearWord32(input_hash,
- Name::kDoesNotContainCachedArrayIndexMask),
- &if_inputcached, &if_inputnotcached);
-
- BIND(&if_inputcached);
- {
- // Just return the {input}s cached array index.
- TNode<UintPtrT> input_array_index =
- DecodeWordFromWord32<String::ArrayIndexValueBits>(input_hash);
- Return(SmiTag(Signed(input_array_index)));
- }
-
- BIND(&if_inputnotcached);
- {
- // Need to fall back to the runtime to convert {input} to double.
- Return(CallRuntime(Runtime::kStringParseFloat, context, input));
- }
- }
-
- BIND(&if_inputisnotstring);
- {
- // The {input} is neither a String nor a Smi, check for HeapNumber.
- Label if_inputisnumber(this),
- if_inputisnotnumber(this, Label::kDeferred);
- Branch(IsHeapNumberMap(input_map), &if_inputisnumber,
- &if_inputisnotnumber);
-
- BIND(&if_inputisnumber);
- {
- // The {input} is already a Number, take care of -0.
- Label if_inputiszero(this), if_inputisnotzero(this);
- TNode<Float64T> input_value = LoadHeapNumberValue(input_heap_object);
- Branch(Float64Equal(input_value, Float64Constant(0.0)),
- &if_inputiszero, &if_inputisnotzero);
-
- BIND(&if_inputiszero);
- Return(SmiConstant(0));
-
- BIND(&if_inputisnotzero);
- Return(input);
- }
-
- BIND(&if_inputisnotnumber);
- {
- // Need to convert the {input} to String first.
- // TODO(bmeurer): This could be more efficient if necessary.
- var_input = CallBuiltin(Builtins::kToString, context, input);
- Goto(&loop);
- }
- }
- }
- }
-}
-
-// ES6 #sec-number.parseint
-TF_BUILTIN(ParseInt, CodeStubAssembler) {
- TNode<Context> context = CAST(Parameter(Descriptor::kContext));
- TNode<Object> input = CAST(Parameter(Descriptor::kString));
- TNode<Object> radix = CAST(Parameter(Descriptor::kRadix));
-
- // Check if {radix} is treated as 10 (i.e. undefined, 0 or 10).
- Label if_radix10(this), if_generic(this, Label::kDeferred);
- GotoIf(IsUndefined(radix), &if_radix10);
- GotoIf(TaggedEqual(radix, SmiConstant(10)), &if_radix10);
- GotoIf(TaggedEqual(radix, SmiConstant(0)), &if_radix10);
- Goto(&if_generic);
-
- BIND(&if_radix10);
- {
- // Check if we can avoid the ToString conversion on {input}.
- Label if_inputissmi(this), if_inputisheapnumber(this),
- if_inputisstring(this);
- GotoIf(TaggedIsSmi(input), &if_inputissmi);
- TNode<Map> input_map = LoadMap(CAST(input));
- GotoIf(IsHeapNumberMap(input_map), &if_inputisheapnumber);
- TNode<Uint16T> input_instance_type = LoadMapInstanceType(input_map);
- Branch(IsStringInstanceType(input_instance_type), &if_inputisstring,
- &if_generic);
-
- BIND(&if_inputissmi);
- {
- // Just return the {input}.
- Return(input);
- }
-
- BIND(&if_inputisheapnumber);
- {
- // Check if the {input} value is in Signed32 range.
- Label if_inputissigned32(this);
- TNode<Float64T> input_value = LoadHeapNumberValue(CAST(input));
- TNode<Int32T> input_value32 =
- Signed(TruncateFloat64ToWord32(input_value));
- GotoIf(Float64Equal(input_value, ChangeInt32ToFloat64(input_value32)),
- &if_inputissigned32);
-
- // Check if the absolute {input} value is in the [1,1<<31[ range.
- // Take the generic path for the range [0,1[ because the result
- // could be -0.
- TNode<Float64T> input_value_abs = Float64Abs(input_value);
-
- GotoIfNot(Float64LessThan(input_value_abs, Float64Constant(1u << 31)),
- &if_generic);
- Branch(Float64LessThanOrEqual(Float64Constant(1), input_value_abs),
- &if_inputissigned32, &if_generic);
-
- // Return the truncated int32 value, and return the tagged result.
- BIND(&if_inputissigned32);
- TNode<Number> result = ChangeInt32ToTagged(input_value32);
- Return(result);
- }
-
- BIND(&if_inputisstring);
- {
- // Check if the String {input} has a cached array index.
- TNode<Uint32T> input_hash = LoadNameHashField(CAST(input));
- GotoIf(IsSetWord32(input_hash, Name::kDoesNotContainCachedArrayIndexMask),
- &if_generic);
-
- // Return the cached array index as result.
- TNode<UintPtrT> input_index =
- DecodeWordFromWord32<String::ArrayIndexValueBits>(input_hash);
- TNode<Smi> result = SmiTag(Signed(input_index));
- Return(result);
- }
- }
-
- BIND(&if_generic);
- {
- TNode<Object> result =
- CallRuntime(Runtime::kStringParseInt, context, input, radix);
- Return(result);
- }
-}
-
-// ES6 #sec-number.parseint
-TF_BUILTIN(NumberParseInt, CodeStubAssembler) {
+#define DEF_BINOP(Name, Generator) \
+ TF_BUILTIN(Name, CodeStubAssembler) { \
+ TNode<Object> lhs = CAST(Parameter(Descriptor::kLeft)); \
+ TNode<Object> rhs = CAST(Parameter(Descriptor::kRight)); \
+ TNode<Context> context = CAST(Parameter(Descriptor::kContext)); \
+ TNode<HeapObject> maybe_feedback_vector = \
+ CAST(Parameter(Descriptor::kMaybeFeedbackVector)); \
+ TNode<UintPtrT> slot = \
+ UncheckedCast<UintPtrT>(Parameter(Descriptor::kSlot)); \
+ \
+ BinaryOpAssembler binop_asm(state()); \
+ TNode<Object> result = binop_asm.Generator(context, lhs, rhs, slot, \
+ maybe_feedback_vector, false); \
+ \
+ Return(result); \
+ }
+DEF_BINOP(Add_WithFeedback, Generate_AddWithFeedback)
+DEF_BINOP(Subtract_WithFeedback, Generate_SubtractWithFeedback)
+DEF_BINOP(Multiply_WithFeedback, Generate_MultiplyWithFeedback)
+DEF_BINOP(Divide_WithFeedback, Generate_DivideWithFeedback)
+DEF_BINOP(Modulus_WithFeedback, Generate_ModulusWithFeedback)
+DEF_BINOP(Exponentiate_WithFeedback, Generate_ExponentiateWithFeedback)
+DEF_BINOP(BitwiseOr_WithFeedback, Generate_BitwiseOrWithFeedback)
+DEF_BINOP(BitwiseXor_WithFeedback, Generate_BitwiseXorWithFeedback)
+DEF_BINOP(BitwiseAnd_WithFeedback, Generate_BitwiseAndWithFeedback)
+DEF_BINOP(ShiftLeft_WithFeedback, Generate_ShiftLeftWithFeedback)
+DEF_BINOP(ShiftRight_WithFeedback, Generate_ShiftRightWithFeedback)
+DEF_BINOP(ShiftRightLogical_WithFeedback,
+ Generate_ShiftRightLogicalWithFeedback)
+#undef DEF_BINOP
+
+#define DEF_UNOP(Name, Generator) \
+ TF_BUILTIN(Name, CodeStubAssembler) { \
+ TNode<Object> value = CAST(Parameter(Descriptor::kValue)); \
+ TNode<Context> context = CAST(Parameter(Descriptor::kContext)); \
+ TNode<HeapObject> maybe_feedback_vector = \
+ CAST(Parameter(Descriptor::kMaybeFeedbackVector)); \
+ TNode<UintPtrT> slot = \
+ UncheckedCast<UintPtrT>(Parameter(Descriptor::kSlot)); \
+ \
+ UnaryOpAssembler a(state()); \
+ TNode<Object> result = \
+ a.Generator(context, value, slot, maybe_feedback_vector); \
+ \
+ Return(result); \
+ }
+DEF_UNOP(BitwiseNot_WithFeedback, Generate_BitwiseNotWithFeedback)
+DEF_UNOP(Decrement_WithFeedback, Generate_DecrementWithFeedback)
+DEF_UNOP(Increment_WithFeedback, Generate_IncrementWithFeedback)
+DEF_UNOP(Negate_WithFeedback, Generate_NegateWithFeedback)
+#undef DEF_UNOP
+
+#define DEF_COMPARE(Name) \
+ TF_BUILTIN(Name##_WithFeedback, CodeStubAssembler) { \
+ TNode<Object> lhs = CAST(Parameter(Descriptor::kLeft)); \
+ TNode<Object> rhs = CAST(Parameter(Descriptor::kRight)); \
+ TNode<Context> context = CAST(Parameter(Descriptor::kContext)); \
+ TNode<HeapObject> maybe_feedback_vector = \
+ CAST(Parameter(Descriptor::kMaybeFeedbackVector)); \
+ TNode<UintPtrT> slot = \
+ UncheckedCast<UintPtrT>(Parameter(Descriptor::kSlot)); \
+ \
+ TVARIABLE(Smi, var_type_feedback); \
+ TNode<Oddball> result = RelationalComparison(Operation::k##Name, lhs, rhs, \
+ context, &var_type_feedback); \
+ UpdateFeedback(var_type_feedback.value(), maybe_feedback_vector, slot); \
+ \
+ Return(result); \
+ }
+DEF_COMPARE(LessThan)
+DEF_COMPARE(LessThanOrEqual)
+DEF_COMPARE(GreaterThan)
+DEF_COMPARE(GreaterThanOrEqual)
+#undef DEF_COMPARE
+
+TF_BUILTIN(Equal_WithFeedback, CodeStubAssembler) {
+ TNode<Object> lhs = CAST(Parameter(Descriptor::kLeft));
+ TNode<Object> rhs = CAST(Parameter(Descriptor::kRight));
TNode<Context> context = CAST(Parameter(Descriptor::kContext));
- TNode<Object> input = CAST(Parameter(Descriptor::kString));
- TNode<Object> radix = CAST(Parameter(Descriptor::kRadix));
- Return(CallBuiltin(Builtins::kParseInt, context, input, radix));
-}
+ TNode<HeapObject> maybe_feedback_vector =
+ CAST(Parameter(Descriptor::kMaybeFeedbackVector));
+ TNode<UintPtrT> slot = UncheckedCast<UintPtrT>(Parameter(Descriptor::kSlot));
-// ES6 #sec-number.prototype.valueof
-TF_BUILTIN(NumberPrototypeValueOf, CodeStubAssembler) {
- TNode<Context> context = CAST(Parameter(Descriptor::kContext));
- TNode<Object> receiver = CAST(Parameter(Descriptor::kReceiver));
+ TVARIABLE(Smi, var_type_feedback);
+ TNode<Oddball> result = Equal(lhs, rhs, context, &var_type_feedback);
+ UpdateFeedback(var_type_feedback.value(), maybe_feedback_vector, slot);
- TNode<Object> result = ToThisValue(context, receiver, PrimitiveType::kNumber,
- "Number.prototype.valueOf");
Return(result);
}
-class AddStubAssembler : public CodeStubAssembler {
- public:
- explicit AddStubAssembler(compiler::CodeAssemblerState* state)
- : CodeStubAssembler(state) {}
-
- protected:
- TNode<Object> ConvertReceiver(TNode<JSReceiver> js_receiver,
- TNode<Context> context) {
- // Call ToPrimitive explicitly without hint (whereas ToNumber
- // would pass a "number" hint).
- Callable callable = CodeFactory::NonPrimitiveToPrimitive(isolate());
- return CallStub(callable, context, js_receiver);
- }
-
- void ConvertNonReceiverAndLoop(TVariable<Object>* var_value, Label* loop,
- TNode<Context> context) {
- *var_value =
- CallBuiltin(Builtins::kNonNumberToNumeric, context, var_value->value());
- Goto(loop);
- }
-
- void ConvertAndLoop(TVariable<Object>* var_value,
- TNode<Uint16T> instance_type, Label* loop,
- TNode<Context> context) {
- Label is_not_receiver(this, Label::kDeferred);
- GotoIfNot(IsJSReceiverInstanceType(instance_type), &is_not_receiver);
-
- *var_value = ConvertReceiver(CAST(var_value->value()), context);
- Goto(loop);
-
- BIND(&is_not_receiver);
- ConvertNonReceiverAndLoop(var_value, loop, context);
- }
-};
-
-TF_BUILTIN(Add, AddStubAssembler) {
- TNode<Context> context = CAST(Parameter(Descriptor::kContext));
- TVARIABLE(Object, var_left, CAST(Parameter(Descriptor::kLeft)));
- TVARIABLE(Object, var_right, CAST(Parameter(Descriptor::kRight)));
-
- // Shared entry for floating point addition.
- Label do_double_add(this);
- TVARIABLE(Float64T, var_left_double);
- TVARIABLE(Float64T, var_right_double);
-
- // We might need to loop several times due to ToPrimitive, ToString and/or
- // ToNumeric conversions.
- Label loop(this, {&var_left, &var_right}),
- string_add_convert_left(this, Label::kDeferred),
- string_add_convert_right(this, Label::kDeferred),
- do_bigint_add(this, Label::kDeferred);
- Goto(&loop);
- BIND(&loop);
- {
- TNode<Object> left = var_left.value();
- TNode<Object> right = var_right.value();
-
- Label if_left_smi(this), if_left_heapobject(this);
- Branch(TaggedIsSmi(left), &if_left_smi, &if_left_heapobject);
-
- BIND(&if_left_smi);
- {
- Label if_right_smi(this), if_right_heapobject(this);
- Branch(TaggedIsSmi(right), &if_right_smi, &if_right_heapobject);
-
- BIND(&if_right_smi);
- {
- Label if_overflow(this);
- TNode<Smi> left_smi = CAST(left);
- TNode<Smi> right_smi = CAST(right);
- TNode<Smi> result = TrySmiAdd(left_smi, right_smi, &if_overflow);
- Return(result);
-
- BIND(&if_overflow);
- {
- var_left_double = SmiToFloat64(left_smi);
- var_right_double = SmiToFloat64(right_smi);
- Goto(&do_double_add);
- }
- } // if_right_smi
-
- BIND(&if_right_heapobject);
- {
- TNode<HeapObject> right_heap_object = CAST(right);
- TNode<Map> right_map = LoadMap(right_heap_object);
-
- Label if_right_not_number(this, Label::kDeferred);
- GotoIfNot(IsHeapNumberMap(right_map), &if_right_not_number);
-
- // {right} is a HeapNumber.
- var_left_double = SmiToFloat64(CAST(left));
- var_right_double = LoadHeapNumberValue(right_heap_object);
- Goto(&do_double_add);
-
- BIND(&if_right_not_number);
- {
- TNode<Uint16T> right_instance_type = LoadMapInstanceType(right_map);
- GotoIf(IsStringInstanceType(right_instance_type),
- &string_add_convert_left);
- GotoIf(IsBigIntInstanceType(right_instance_type), &do_bigint_add);
- ConvertAndLoop(&var_right, right_instance_type, &loop, context);
- }
- } // if_right_heapobject
- } // if_left_smi
-
- BIND(&if_left_heapobject);
- {
- TNode<HeapObject> left_heap_object = CAST(left);
- TNode<Map> left_map = LoadMap(left_heap_object);
- Label if_right_smi(this), if_right_heapobject(this);
- Branch(TaggedIsSmi(right), &if_right_smi, &if_right_heapobject);
-
- BIND(&if_right_smi);
- {
- Label if_left_not_number(this, Label::kDeferred);
- GotoIfNot(IsHeapNumberMap(left_map), &if_left_not_number);
-
- // {left} is a HeapNumber, {right} is a Smi.
- var_left_double = LoadHeapNumberValue(left_heap_object);
- var_right_double = SmiToFloat64(CAST(right));
- Goto(&do_double_add);
-
- BIND(&if_left_not_number);
- {
- TNode<Uint16T> left_instance_type = LoadMapInstanceType(left_map);
- GotoIf(IsStringInstanceType(left_instance_type),
- &string_add_convert_right);
- GotoIf(IsBigIntInstanceType(left_instance_type), &do_bigint_add);
- // {left} is neither a Numeric nor a String, and {right} is a Smi.
- ConvertAndLoop(&var_left, left_instance_type, &loop, context);
- }
- } // if_right_smi
-
- BIND(&if_right_heapobject);
- {
- TNode<HeapObject> right_heap_object = CAST(right);
- TNode<Map> right_map = LoadMap(right_heap_object);
-
- Label if_left_number(this), if_left_not_number(this, Label::kDeferred);
- Branch(IsHeapNumberMap(left_map), &if_left_number, &if_left_not_number);
-
- BIND(&if_left_number);
- {
- Label if_right_not_number(this, Label::kDeferred);
- GotoIfNot(IsHeapNumberMap(right_map), &if_right_not_number);
-
- // Both {left} and {right} are HeapNumbers.
- var_left_double = LoadHeapNumberValue(CAST(left));
- var_right_double = LoadHeapNumberValue(right_heap_object);
- Goto(&do_double_add);
-
- BIND(&if_right_not_number);
- {
- TNode<Uint16T> right_instance_type = LoadMapInstanceType(right_map);
- GotoIf(IsStringInstanceType(right_instance_type),
- &string_add_convert_left);
- GotoIf(IsBigIntInstanceType(right_instance_type), &do_bigint_add);
- // {left} is a HeapNumber, {right} is neither Number nor String.
- ConvertAndLoop(&var_right, right_instance_type, &loop, context);
- }
- } // if_left_number
-
- BIND(&if_left_not_number);
- {
- Label if_left_bigint(this);
- TNode<Uint16T> left_instance_type = LoadMapInstanceType(left_map);
- GotoIf(IsStringInstanceType(left_instance_type),
- &string_add_convert_right);
- TNode<Uint16T> right_instance_type = LoadMapInstanceType(right_map);
- GotoIf(IsStringInstanceType(right_instance_type),
- &string_add_convert_left);
- GotoIf(IsBigIntInstanceType(left_instance_type), &if_left_bigint);
- Label if_left_not_receiver(this, Label::kDeferred);
- Label if_right_not_receiver(this, Label::kDeferred);
- GotoIfNot(IsJSReceiverInstanceType(left_instance_type),
- &if_left_not_receiver);
- // {left} is a JSReceiver, convert it first.
- var_left = ConvertReceiver(CAST(var_left.value()), context);
- Goto(&loop);
-
- BIND(&if_left_bigint);
- {
- // {right} is a HeapObject, but not a String. Jump to
- // {do_bigint_add} if {right} is already a Numeric.
- GotoIf(IsBigIntInstanceType(right_instance_type), &do_bigint_add);
- GotoIf(IsHeapNumberMap(right_map), &do_bigint_add);
- ConvertAndLoop(&var_right, right_instance_type, &loop, context);
- }
-
- BIND(&if_left_not_receiver);
- GotoIfNot(IsJSReceiverInstanceType(right_instance_type),
- &if_right_not_receiver);
- // {left} is a Primitive, but {right} is a JSReceiver, so convert
- // {right} with priority.
- var_right = ConvertReceiver(CAST(var_right.value()), context);
- Goto(&loop);
-
- BIND(&if_right_not_receiver);
- // Neither {left} nor {right} are JSReceivers.
- ConvertNonReceiverAndLoop(&var_left, &loop, context);
- }
- } // if_right_heapobject
- } // if_left_heapobject
- }
- BIND(&string_add_convert_left);
- {
- // Convert {left} to a String and concatenate it with the String {right}.
- TailCallBuiltin(Builtins::kStringAddConvertLeft, context, var_left.value(),
- var_right.value());
- }
-
- BIND(&string_add_convert_right);
- {
- // Convert {right} to a String and concatenate it with the String {left}.
- TailCallBuiltin(Builtins::kStringAddConvertRight, context, var_left.value(),
- var_right.value());
- }
-
- BIND(&do_bigint_add);
- {
- TailCallBuiltin(Builtins::kBigIntAdd, context, var_left.value(),
- var_right.value());
- }
-
- BIND(&do_double_add);
- {
- TNode<Float64T> value =
- Float64Add(var_left_double.value(), var_right_double.value());
- Return(AllocateHeapNumberWithValue(value));
- }
-}
-
-template <typename Descriptor>
-void NumberBuiltinsAssembler::UnaryOp(TVariable<Object>* var_input,
- Label* do_smi, Label* do_double,
- TVariable<Float64T>* var_input_double,
- Label* do_bigint) {
- TNode<Context> context = CAST(Parameter(Descriptor::kContext));
- *var_input = CAST(Parameter(Descriptor::kValue));
-
- // We might need to loop for ToNumeric conversion.
- Label loop(this, {var_input});
- Goto(&loop);
- BIND(&loop);
- TNode<Object> input = var_input->value();
-
- Label not_number(this);
- GotoIf(TaggedIsSmi(input), do_smi);
- TNode<HeapObject> input_heap_object = CAST(input);
- GotoIfNot(IsHeapNumber(input_heap_object), &not_number);
- if (var_input_double != nullptr) {
- *var_input_double = LoadHeapNumberValue(input_heap_object);
- }
- Goto(do_double);
-
- BIND(&not_number);
- GotoIf(IsBigInt(input_heap_object), do_bigint);
- *var_input = CallBuiltin(Builtins::kNonNumberToNumeric, context, input);
- Goto(&loop);
-}
-
-template <typename Descriptor>
-void NumberBuiltinsAssembler::BinaryOp(Label* smis, TVariable<Object>* var_left,
- TVariable<Object>* var_right,
- Label* doubles,
- TVariable<Float64T>* var_left_double,
- TVariable<Float64T>* var_right_double,
- Label* bigints) {
- DCHECK_EQ(var_left_double == nullptr, var_right_double == nullptr);
-
- TNode<Context> context = CAST(Parameter(Descriptor::kContext));
- *var_left = CAST(Parameter(Descriptor::kLeft));
- *var_right = CAST(Parameter(Descriptor::kRight));
-
- // We might need to loop for ToNumeric conversions.
- Label loop(this, {var_left, var_right});
- Goto(&loop);
- BIND(&loop);
-
- Label left_not_smi(this), right_not_smi(this);
- Label left_not_number(this), right_not_number(this);
- GotoIfNot(TaggedIsSmi(var_left->value()), &left_not_smi);
- GotoIf(TaggedIsSmi(var_right->value()), smis);
-
- // At this point, var_left is a Smi but var_right is not.
- TNode<Smi> var_left_smi = CAST(var_left->value());
- TNode<HeapObject> var_right_heap_object = CAST(var_right->value());
- GotoIfNot(IsHeapNumber(var_right_heap_object), &right_not_number);
- if (var_left_double != nullptr) {
- *var_left_double = SmiToFloat64(var_left_smi);
- *var_right_double = LoadHeapNumberValue(var_right_heap_object);
- }
- Goto(doubles);
-
- BIND(&left_not_smi);
- {
- TNode<HeapObject> var_left_heap_object = CAST(var_left->value());
- GotoIfNot(IsHeapNumber(var_left_heap_object), &left_not_number);
- GotoIfNot(TaggedIsSmi(var_right->value()), &right_not_smi);
-
- // At this point, var_left is a HeapNumber and var_right is a Smi.
- if (var_left_double != nullptr) {
- *var_left_double = LoadHeapNumberValue(var_left_heap_object);
- *var_right_double = SmiToFloat64(CAST(var_right->value()));
- }
- Goto(doubles);
- }
-
- BIND(&right_not_smi);
- {
- TNode<HeapObject> var_right_heap_object = CAST(var_right->value());
- GotoIfNot(IsHeapNumber(var_right_heap_object), &right_not_number);
- if (var_left_double != nullptr) {
- *var_left_double = LoadHeapNumberValue(CAST(var_left->value()));
- *var_right_double = LoadHeapNumberValue(var_right_heap_object);
- }
- Goto(doubles);
- }
-
- BIND(&left_not_number);
- {
- Label left_bigint(this);
- GotoIf(IsBigInt(CAST(var_left->value())), &left_bigint);
- *var_left =
- CallBuiltin(Builtins::kNonNumberToNumeric, context, var_left->value());
- Goto(&loop);
-
- BIND(&left_bigint);
- {
- // Jump to {bigints} if {var_right} is already a Numeric.
- GotoIf(TaggedIsSmi(var_right->value()), bigints);
- TNode<HeapObject> var_right_heap_object = CAST(var_right->value());
- GotoIf(IsBigInt(var_right_heap_object), bigints);
- GotoIf(IsHeapNumber(var_right_heap_object), bigints);
- *var_right = CallBuiltin(Builtins::kNonNumberToNumeric, context,
- var_right->value());
- Goto(&loop);
- }
- }
-
- BIND(&right_not_number);
- {
- GotoIf(IsBigInt(CAST(var_right->value())), bigints);
- *var_right =
- CallBuiltin(Builtins::kNonNumberToNumeric, context, var_right->value());
- Goto(&loop);
- }
-}
-
-TF_BUILTIN(Subtract, NumberBuiltinsAssembler) {
- TVARIABLE(Object, var_left);
- TVARIABLE(Object, var_right);
- TVARIABLE(Float64T, var_left_double);
- TVARIABLE(Float64T, var_right_double);
- Label do_smi_sub(this), do_double_sub(this), do_bigint_sub(this);
-
- BinaryOp<Descriptor>(&do_smi_sub, &var_left, &var_right, &do_double_sub,
- &var_left_double, &var_right_double, &do_bigint_sub);
-
- BIND(&do_smi_sub);
- {
- Label if_overflow(this);
- TNode<Smi> var_left_smi = CAST(var_left.value());
- TNode<Smi> var_right_smi = CAST(var_right.value());
- TNode<Smi> result = TrySmiSub(var_left_smi, var_right_smi, &if_overflow);
- Return(result);
-
- BIND(&if_overflow);
- {
- var_left_double = SmiToFloat64(var_left_smi);
- var_right_double = SmiToFloat64(var_right_smi);
- Goto(&do_double_sub);
- }
- }
-
- BIND(&do_double_sub);
- {
- TNode<Float64T> value =
- Float64Sub(var_left_double.value(), var_right_double.value());
- Return(AllocateHeapNumberWithValue(value));
- }
-
- BIND(&do_bigint_sub);
- {
- TNode<Context> context = CAST(Parameter(Descriptor::kContext));
- TailCallBuiltin(Builtins::kBigIntSubtract, context, var_left.value(),
- var_right.value());
- }
-}
-
-TF_BUILTIN(BitwiseNot, NumberBuiltinsAssembler) {
- TNode<Context> context = CAST(Parameter(Descriptor::kContext));
- TVARIABLE(Object, var_input);
- Label do_number(this), do_bigint(this);
-
- UnaryOp<Descriptor>(&var_input, &do_number, &do_number, nullptr, &do_bigint);
-
- BIND(&do_number);
- {
- TailCallBuiltin(Builtins::kBitwiseXor, context, var_input.value(),
- SmiConstant(-1));
- }
-
- BIND(&do_bigint);
- {
- Return(CallRuntime(Runtime::kBigIntUnaryOp, context, var_input.value(),
- SmiConstant(Operation::kBitwiseNot)));
- }
-}
-
-TF_BUILTIN(Decrement, NumberBuiltinsAssembler) {
- TNode<Context> context = CAST(Parameter(Descriptor::kContext));
- TVARIABLE(Object, var_input);
- Label do_number(this), do_bigint(this);
-
- UnaryOp<Descriptor>(&var_input, &do_number, &do_number, nullptr, &do_bigint);
-
- BIND(&do_number);
- {
- TailCallBuiltin(Builtins::kSubtract, context, var_input.value(),
- SmiConstant(1));
- }
-
- BIND(&do_bigint);
- {
- Return(CallRuntime(Runtime::kBigIntUnaryOp, context, var_input.value(),
- SmiConstant(Operation::kDecrement)));
- }
-}
-
-TF_BUILTIN(Increment, NumberBuiltinsAssembler) {
- TNode<Context> context = CAST(Parameter(Descriptor::kContext));
- TVARIABLE(Object, var_input);
- Label do_number(this), do_bigint(this);
-
- UnaryOp<Descriptor>(&var_input, &do_number, &do_number, nullptr, &do_bigint);
-
- BIND(&do_number);
- {
- TailCallBuiltin(Builtins::kAdd, context, var_input.value(), SmiConstant(1));
- }
-
- BIND(&do_bigint);
- {
- Return(CallRuntime(Runtime::kBigIntUnaryOp, context, var_input.value(),
- SmiConstant(Operation::kIncrement)));
- }
-}
-
-TF_BUILTIN(Negate, NumberBuiltinsAssembler) {
- TVARIABLE(Object, var_input);
- TVARIABLE(Float64T, var_input_double);
- Label do_smi(this), do_double(this), do_bigint(this);
-
- UnaryOp<Descriptor>(&var_input, &do_smi, &do_double, &var_input_double,
- &do_bigint);
-
- BIND(&do_smi);
- { Return(SmiMul(CAST(var_input.value()), SmiConstant(-1))); }
-
- BIND(&do_double);
- {
- TNode<Float64T> value =
- Float64Mul(var_input_double.value(), Float64Constant(-1));
- Return(AllocateHeapNumberWithValue(value));
- }
-
- BIND(&do_bigint);
- {
- TNode<Context> context = CAST(Parameter(Descriptor::kContext));
- Return(CallRuntime(Runtime::kBigIntUnaryOp, context, var_input.value(),
- SmiConstant(Operation::kNegate)));
- }
-}
-
-TF_BUILTIN(Multiply, NumberBuiltinsAssembler) {
- TVARIABLE(Object, var_left);
- TVARIABLE(Object, var_right);
- TVARIABLE(Float64T, var_left_double);
- TVARIABLE(Float64T, var_right_double);
- Label do_smi_mul(this), do_double_mul(this), do_bigint_mul(this);
-
- BinaryOp<Descriptor>(&do_smi_mul, &var_left, &var_right, &do_double_mul,
- &var_left_double, &var_right_double, &do_bigint_mul);
-
- BIND(&do_smi_mul);
- // The result is not necessarily a smi, in case of overflow.
- Return(SmiMul(CAST(var_left.value()), CAST(var_right.value())));
-
- BIND(&do_double_mul);
- TNode<Float64T> value =
- Float64Mul(var_left_double.value(), var_right_double.value());
- Return(AllocateHeapNumberWithValue(value));
-
- BIND(&do_bigint_mul);
- {
- TNode<Context> context = CAST(Parameter(Descriptor::kContext));
- Return(CallRuntime(Runtime::kBigIntBinaryOp, context, var_left.value(),
- var_right.value(), SmiConstant(Operation::kMultiply)));
- }
-}
-
-TF_BUILTIN(Divide, NumberBuiltinsAssembler) {
- TVARIABLE(Object, var_left);
- TVARIABLE(Object, var_right);
- TVARIABLE(Float64T, var_left_double);
- TVARIABLE(Float64T, var_right_double);
- Label do_smi_div(this), do_double_div(this), do_bigint_div(this);
-
- BinaryOp<Descriptor>(&do_smi_div, &var_left, &var_right, &do_double_div,
- &var_left_double, &var_right_double, &do_bigint_div);
-
- BIND(&do_smi_div);
- {
- // TODO(jkummerow): Consider just always doing a double division.
- Label bailout(this);
- TNode<Smi> dividend = CAST(var_left.value());
- TNode<Smi> divisor = CAST(var_right.value());
-
- // Do floating point division if {divisor} is zero.
- GotoIf(SmiEqual(divisor, SmiConstant(0)), &bailout);
-
- // Do floating point division if {dividend} is zero and {divisor} is
- // negative.
- Label dividend_is_zero(this), dividend_is_not_zero(this);
- Branch(SmiEqual(dividend, SmiConstant(0)), &dividend_is_zero,
- &dividend_is_not_zero);
-
- BIND(&dividend_is_zero);
- {
- GotoIf(SmiLessThan(divisor, SmiConstant(0)), &bailout);
- Goto(&dividend_is_not_zero);
- }
- BIND(&dividend_is_not_zero);
-
- TNode<Int32T> untagged_divisor = SmiToInt32(divisor);
- TNode<Int32T> untagged_dividend = SmiToInt32(dividend);
-
- // Do floating point division if {dividend} is kMinInt (or kMinInt - 1
- // if the Smi size is 31) and {divisor} is -1.
- Label divisor_is_minus_one(this), divisor_is_not_minus_one(this);
- Branch(Word32Equal(untagged_divisor, Int32Constant(-1)),
- &divisor_is_minus_one, &divisor_is_not_minus_one);
-
- BIND(&divisor_is_minus_one);
- {
- GotoIf(Word32Equal(
- untagged_dividend,
- Int32Constant(kSmiValueSize == 32 ? kMinInt : (kMinInt >> 1))),
- &bailout);
- Goto(&divisor_is_not_minus_one);
- }
- BIND(&divisor_is_not_minus_one);
-
- // TODO(epertoso): consider adding a machine instruction that returns
- // both the result and the remainder.
- TNode<Int32T> untagged_result =
- Int32Div(untagged_dividend, untagged_divisor);
- TNode<Int32T> truncated = Int32Mul(untagged_result, untagged_divisor);
- // Do floating point division if the remainder is not 0.
- GotoIf(Word32NotEqual(untagged_dividend, truncated), &bailout);
- Return(SmiFromInt32(untagged_result));
-
- // Bailout: convert {dividend} and {divisor} to double and do double
- // division.
- BIND(&bailout);
- {
- var_left_double = SmiToFloat64(dividend);
- var_right_double = SmiToFloat64(divisor);
- Goto(&do_double_div);
- }
- }
-
- BIND(&do_double_div);
- {
- TNode<Float64T> value =
- Float64Div(var_left_double.value(), var_right_double.value());
- Return(AllocateHeapNumberWithValue(value));
- }
-
- BIND(&do_bigint_div);
- {
- TNode<Context> context = CAST(Parameter(Descriptor::kContext));
- Return(CallRuntime(Runtime::kBigIntBinaryOp, context, var_left.value(),
- var_right.value(), SmiConstant(Operation::kDivide)));
- }
-}
-
-TF_BUILTIN(Modulus, NumberBuiltinsAssembler) {
- TVARIABLE(Object, var_left);
- TVARIABLE(Object, var_right);
- TVARIABLE(Float64T, var_left_double);
- TVARIABLE(Float64T, var_right_double);
- Label do_smi_mod(this), do_double_mod(this), do_bigint_mod(this);
-
- BinaryOp<Descriptor>(&do_smi_mod, &var_left, &var_right, &do_double_mod,
- &var_left_double, &var_right_double, &do_bigint_mod);
-
- BIND(&do_smi_mod);
- Return(SmiMod(CAST(var_left.value()), CAST(var_right.value())));
-
- BIND(&do_double_mod);
- TNode<Float64T> value =
- Float64Mod(var_left_double.value(), var_right_double.value());
- Return(AllocateHeapNumberWithValue(value));
-
- BIND(&do_bigint_mod);
- {
- TNode<Context> context = CAST(Parameter(Descriptor::kContext));
- Return(CallRuntime(Runtime::kBigIntBinaryOp, context, var_left.value(),
- var_right.value(), SmiConstant(Operation::kModulus)));
- }
-}
-
-TF_BUILTIN(Exponentiate, NumberBuiltinsAssembler) {
- TVARIABLE(Object, var_left);
- TVARIABLE(Object, var_right);
- Label do_number_exp(this), do_bigint_exp(this);
- TNode<Context> context = CAST(Parameter(Descriptor::kContext));
-
- BinaryOp<Descriptor>(&do_number_exp, &var_left, &var_right, &do_number_exp,
- nullptr, nullptr, &do_bigint_exp);
-
- BIND(&do_number_exp);
- { Return(MathPowImpl(context, var_left.value(), var_right.value())); }
-
- BIND(&do_bigint_exp);
- Return(CallRuntime(Runtime::kBigIntBinaryOp, context, var_left.value(),
- var_right.value(), SmiConstant(Operation::kExponentiate)));
-}
-
-TF_BUILTIN(ShiftLeft, NumberBuiltinsAssembler) {
- EmitBitwiseOp<Descriptor>(Operation::kShiftLeft);
-}
-
-TF_BUILTIN(ShiftRight, NumberBuiltinsAssembler) {
- EmitBitwiseOp<Descriptor>(Operation::kShiftRight);
-}
-
-TF_BUILTIN(ShiftRightLogical, NumberBuiltinsAssembler) {
- EmitBitwiseOp<Descriptor>(Operation::kShiftRightLogical);
-}
-
-TF_BUILTIN(BitwiseAnd, NumberBuiltinsAssembler) {
- EmitBitwiseOp<Descriptor>(Operation::kBitwiseAnd);
-}
-
-TF_BUILTIN(BitwiseOr, NumberBuiltinsAssembler) {
- EmitBitwiseOp<Descriptor>(Operation::kBitwiseOr);
-}
-
-TF_BUILTIN(BitwiseXor, NumberBuiltinsAssembler) {
- EmitBitwiseOp<Descriptor>(Operation::kBitwiseXor);
-}
-
-TF_BUILTIN(LessThan, NumberBuiltinsAssembler) {
- RelationalComparisonBuiltin<Descriptor>(Operation::kLessThan);
-}
-
-TF_BUILTIN(LessThanOrEqual, NumberBuiltinsAssembler) {
- RelationalComparisonBuiltin<Descriptor>(Operation::kLessThanOrEqual);
-}
-
-TF_BUILTIN(GreaterThan, NumberBuiltinsAssembler) {
- RelationalComparisonBuiltin<Descriptor>(Operation::kGreaterThan);
-}
-
-TF_BUILTIN(GreaterThanOrEqual, NumberBuiltinsAssembler) {
- RelationalComparisonBuiltin<Descriptor>(Operation::kGreaterThanOrEqual);
-}
-
-TF_BUILTIN(Equal, CodeStubAssembler) {
+TF_BUILTIN(StrictEqual_WithFeedback, CodeStubAssembler) {
TNode<Object> lhs = CAST(Parameter(Descriptor::kLeft));
TNode<Object> rhs = CAST(Parameter(Descriptor::kRight));
- TNode<Context> context = CAST(Parameter(Descriptor::kContext));
+ TNode<HeapObject> maybe_feedback_vector =
+ CAST(Parameter(Descriptor::kMaybeFeedbackVector));
+ TNode<UintPtrT> slot = UncheckedCast<UintPtrT>(Parameter(Descriptor::kSlot));
- Return(Equal(lhs, rhs, context));
-}
+ TVARIABLE(Smi, var_type_feedback);
+ TNode<Oddball> result = StrictEqual(lhs, rhs, &var_type_feedback);
+ UpdateFeedback(var_type_feedback.value(), maybe_feedback_vector, slot);
-TF_BUILTIN(StrictEqual, CodeStubAssembler) {
- TNode<Object> lhs = CAST(Parameter(Descriptor::kLeft));
- TNode<Object> rhs = CAST(Parameter(Descriptor::kRight));
-
- Return(StrictEqual(lhs, rhs));
+ Return(result);
}
} // namespace internal
diff --git a/chromium/v8/src/builtins/builtins-object-gen.cc b/chromium/v8/src/builtins/builtins-object-gen.cc
index 06045495581..43a0a6953e8 100644
--- a/chromium/v8/src/builtins/builtins-object-gen.cc
+++ b/chromium/v8/src/builtins/builtins-object-gen.cc
@@ -314,7 +314,8 @@ TNode<JSArray> ObjectEntriesValuesBuiltinsAssembler::FastGetOwnValuesOrEntries(
TNode<JSArray> array;
TNode<FixedArrayBase> elements;
std::tie(array, elements) = AllocateUninitializedJSArrayWithElements(
- PACKED_ELEMENTS, array_map, SmiConstant(2), {}, IntPtrConstant(2));
+ PACKED_ELEMENTS, array_map, SmiConstant(2), base::nullopt,
+ IntPtrConstant(2));
StoreFixedArrayElement(CAST(elements), 0, next_key, SKIP_WRITE_BARRIER);
StoreFixedArrayElement(CAST(elements), 1, value, SKIP_WRITE_BARRIER);
value = TNode<JSArray>::UncheckedCast(array);
@@ -499,7 +500,7 @@ TF_BUILTIN(ObjectKeys, ObjectBuiltinsAssembler) {
LoadJSArrayElementsMap(PACKED_ELEMENTS, native_context);
TNode<Smi> array_length = SmiTag(Signed(object_enum_length));
std::tie(array, elements) = AllocateUninitializedJSArrayWithElements(
- PACKED_ELEMENTS, array_map, array_length, {},
+ PACKED_ELEMENTS, array_map, array_length, base::nullopt,
Signed(object_enum_length));
CopyFixedArrayElements(PACKED_ELEMENTS, object_enum_keys, elements,
object_enum_length, SKIP_WRITE_BARRIER);
@@ -595,7 +596,7 @@ TF_BUILTIN(ObjectGetOwnPropertyNames, ObjectBuiltinsAssembler) {
TNode<JSArray> array;
TNode<FixedArrayBase> elements;
std::tie(array, elements) = AllocateUninitializedJSArrayWithElements(
- PACKED_ELEMENTS, array_map, array_length, {},
+ PACKED_ELEMENTS, array_map, array_length, base::nullopt,
Signed(object_enum_length));
CopyFixedArrayElements(PACKED_ELEMENTS, object_enum_keys, elements,
object_enum_length, SKIP_WRITE_BARRIER);
diff --git a/chromium/v8/src/builtins/builtins-promise.h b/chromium/v8/src/builtins/builtins-promise.h
index fd938ff8418..a775ea20411 100644
--- a/chromium/v8/src/builtins/builtins-promise.h
+++ b/chromium/v8/src/builtins/builtins-promise.h
@@ -35,7 +35,7 @@ class PromiseBuiltins {
kPromiseAllResolveElementCapabilitySlot,
// Values array from Promise.all
- kPromiseAllResolveElementValuesArraySlot,
+ kPromiseAllResolveElementValuesSlot,
kPromiseAllResolveElementLength
};
@@ -48,7 +48,7 @@ class PromiseBuiltins {
kPromiseAnyRejectElementCapabilitySlot,
// errors array from Promise.any
- kPromiseAnyRejectElementErrorsArraySlot,
+ kPromiseAnyRejectElementErrorsSlot,
kPromiseAnyRejectElementLength
};
diff --git a/chromium/v8/src/builtins/builtins-regexp-gen.cc b/chromium/v8/src/builtins/builtins-regexp-gen.cc
index b9c1b8980ea..584111cc760 100644
--- a/chromium/v8/src/builtins/builtins-regexp-gen.cc
+++ b/chromium/v8/src/builtins/builtins-regexp-gen.cc
@@ -89,7 +89,7 @@ TNode<JSRegExpResult> RegExpBuiltinsAssembler::AllocateRegExpResult(
const ElementsKind elements_kind = PACKED_ELEMENTS;
TNode<Map> map = CAST(LoadContextElement(LoadNativeContext(context),
Context::REGEXP_RESULT_MAP_INDEX));
- TNode<AllocationSite> no_allocation_site = {};
+ base::Optional<TNode<AllocationSite>> no_allocation_site = base::nullopt;
TNode<IntPtrT> length_intptr = SmiUntag(length);
// Note: The returned `elements` may be in young large object space, but
@@ -1354,9 +1354,7 @@ TNode<JSArray> RegExpBuiltinsAssembler::RegExpPrototypeSplitBody(
const TNode<IntPtrT> int_limit = SmiUntag(limit);
const ElementsKind kind = PACKED_ELEMENTS;
- const ParameterMode mode = CodeStubAssembler::INTPTR_PARAMETERS;
- TNode<AllocationSite> allocation_site = {};
const TNode<NativeContext> native_context = LoadNativeContext(context);
TNode<Map> array_map = LoadJSArrayElementsMap(kind, native_context);
@@ -1396,6 +1394,7 @@ TNode<JSArray> RegExpBuiltinsAssembler::RegExpPrototypeSplitBody(
{
TNode<Smi> length = SmiConstant(1);
TNode<IntPtrT> capacity = IntPtrConstant(1);
+ base::Optional<TNode<AllocationSite>> allocation_site = base::nullopt;
var_result =
AllocateJSArray(kind, array_map, capacity, length, allocation_site);
@@ -1508,10 +1507,10 @@ TNode<JSArray> RegExpBuiltinsAssembler::RegExpPrototypeSplitBody(
const TNode<IntPtrT> reg = var_reg.value();
const TNode<Object> from = LoadFixedArrayElement(
match_indices, reg,
- RegExpMatchInfo::kFirstCaptureIndex * kTaggedSize, mode);
+ RegExpMatchInfo::kFirstCaptureIndex * kTaggedSize);
const TNode<Smi> to = CAST(LoadFixedArrayElement(
match_indices, reg,
- (RegExpMatchInfo::kFirstCaptureIndex + 1) * kTaggedSize, mode));
+ (RegExpMatchInfo::kFirstCaptureIndex + 1) * kTaggedSize));
Label select_capture(this), select_undefined(this), store_value(this);
TVARIABLE(Object, var_value);
@@ -1570,6 +1569,7 @@ TNode<JSArray> RegExpBuiltinsAssembler::RegExpPrototypeSplitBody(
{
TNode<Smi> length = SmiZero();
TNode<IntPtrT> capacity = IntPtrZero();
+ base::Optional<TNode<AllocationSite>> allocation_site = base::nullopt;
var_result =
AllocateJSArray(kind, array_map, capacity, length, allocation_site);
Goto(&done);
diff --git a/chromium/v8/src/builtins/builtins-string-gen.cc b/chromium/v8/src/builtins/builtins-string-gen.cc
index 7ccb99792ed..9920369136a 100644
--- a/chromium/v8/src/builtins/builtins-string-gen.cc
+++ b/chromium/v8/src/builtins/builtins-string-gen.cc
@@ -1164,10 +1164,11 @@ void StringBuiltinsAssembler::MaybeCallFunctionAtSymbol(
DescriptorIndexNameValue additional_property_to_check,
const NodeFunction0& regexp_call, const NodeFunction1& generic_call) {
Label out(this);
+ Label get_property_lookup(this);
- // Smis definitely don't have an attached symbol.
- GotoIf(TaggedIsSmi(object), &out);
- TNode<HeapObject> heap_object = CAST(object);
+ // Smis have to go through the GetProperty lookup in case Number.prototype or
+ // Object.prototype was modified.
+ GotoIf(TaggedIsSmi(object), &get_property_lookup);
// Take the fast path for RegExps.
// There's two conditions: {object} needs to be a fast regexp, and
@@ -1176,6 +1177,8 @@ void StringBuiltinsAssembler::MaybeCallFunctionAtSymbol(
{
Label stub_call(this), slow_lookup(this);
+ TNode<HeapObject> heap_object = CAST(object);
+
GotoIf(TaggedIsSmi(maybe_string), &slow_lookup);
GotoIfNot(IsString(CAST(maybe_string)), &slow_lookup);
@@ -1196,10 +1199,10 @@ void StringBuiltinsAssembler::MaybeCallFunctionAtSymbol(
regexp_call();
BIND(&slow_lookup);
+ // Special case null and undefined to skip the property lookup.
+ Branch(IsNullOrUndefined(heap_object), &out, &get_property_lookup);
}
- GotoIf(IsNullOrUndefined(heap_object), &out);
-
// Fall back to a slow lookup of {heap_object[symbol]}.
//
// The spec uses GetMethod({heap_object}, {symbol}), which has a few quirks:
@@ -1208,7 +1211,8 @@ void StringBuiltinsAssembler::MaybeCallFunctionAtSymbol(
// We handle the former by jumping to {out} for null values as well, while
// the latter is already handled by the Call({maybe_func}) operation.
- const TNode<Object> maybe_func = GetProperty(context, heap_object, symbol);
+ BIND(&get_property_lookup);
+ const TNode<Object> maybe_func = GetProperty(context, object, symbol);
GotoIf(IsUndefined(maybe_func), &out);
GotoIf(IsNull(maybe_func), &out);
diff --git a/chromium/v8/src/builtins/builtins-string.cc b/chromium/v8/src/builtins/builtins-string.cc
index 8a897765c83..df5ba93a59e 100644
--- a/chromium/v8/src/builtins/builtins-string.cc
+++ b/chromium/v8/src/builtins/builtins-string.cc
@@ -40,14 +40,16 @@ bool IsValidCodePoint(Isolate* isolate, Handle<Object> value) {
return true;
}
+static constexpr uc32 kInvalidCodePoint = static_cast<uc32>(-1);
+
uc32 NextCodePoint(Isolate* isolate, BuiltinArguments args, int index) {
Handle<Object> value = args.at(1 + index);
- ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, value,
- Object::ToNumber(isolate, value), -1);
+ ASSIGN_RETURN_ON_EXCEPTION_VALUE(
+ isolate, value, Object::ToNumber(isolate, value), kInvalidCodePoint);
if (!IsValidCodePoint(isolate, value)) {
isolate->Throw(*isolate->factory()->NewRangeError(
MessageTemplate::kInvalidCodePoint, value));
- return -1;
+ return kInvalidCodePoint;
}
return DoubleToUint32(value->Number());
}
@@ -69,7 +71,7 @@ BUILTIN(StringFromCodePoint) {
int index;
for (index = 0; index < length; index++) {
code = NextCodePoint(isolate, args, index);
- if (code < 0) {
+ if (code == kInvalidCodePoint) {
return ReadOnlyRoots(isolate).exception();
}
if (code > String::kMaxOneByteCharCode) {
@@ -99,7 +101,7 @@ BUILTIN(StringFromCodePoint) {
break;
}
code = NextCodePoint(isolate, args, index);
- if (code < 0) {
+ if (code == kInvalidCodePoint) {
return ReadOnlyRoots(isolate).exception();
}
}
diff --git a/chromium/v8/src/builtins/builtins-string.tq b/chromium/v8/src/builtins/builtins-string.tq
index a4edc94418c..6ec7bc9d0ac 100644
--- a/chromium/v8/src/builtins/builtins-string.tq
+++ b/chromium/v8/src/builtins/builtins-string.tq
@@ -5,6 +5,43 @@
#include 'src/builtins/builtins-string-gen.h'
namespace string {
+
+// TODO(bbudge) Remove the 'RT' suffix on this runtime function.
+extern transitioning runtime ToStringRT(Context, JSAny): String;
+
+@export
+transitioning macro ToStringImpl(context: Context, o: JSAny): String {
+ let result: JSAny = o;
+ while (true) {
+ typeswitch (result) {
+ case (num: Number): {
+ return NumberToString(num);
+ }
+ case (str: String): {
+ return str;
+ }
+ case (oddball: Oddball): {
+ return oddball.to_string;
+ }
+ case (JSReceiver): {
+ result = NonPrimitiveToPrimitive_String(context, result);
+ continue;
+ }
+ case (Symbol): {
+ ThrowTypeError(MessageTemplate::kSymbolToString);
+ }
+ case (JSAny): {
+ return ToStringRT(context, o);
+ }
+ }
+ }
+ unreachable;
+}
+
+transitioning builtin ToString(context: Context, o: JSAny): String {
+ return ToStringImpl(context, o);
+}
+
extern macro StringBuiltinsAssembler::SubString(
String, uintptr, uintptr): String;
diff --git a/chromium/v8/src/builtins/builtins-typed-array-gen.cc b/chromium/v8/src/builtins/builtins-typed-array-gen.cc
index a6d3887ad31..b359b438c74 100644
--- a/chromium/v8/src/builtins/builtins-typed-array-gen.cc
+++ b/chromium/v8/src/builtins/builtins-typed-array-gen.cc
@@ -505,49 +505,5 @@ TF_BUILTIN(TypedArrayPrototypeToStringTag, TypedArrayBuiltinsAssembler) {
BIND(&return_undefined);
Return(UndefinedConstant());
}
-
-void TypedArrayBuiltinsAssembler::GenerateTypedArrayPrototypeIterationMethod(
- TNode<Context> context, TNode<Object> receiver, const char* method_name,
- IterationKind kind) {
- Label throw_bad_receiver(this, Label::kDeferred);
-
- GotoIf(TaggedIsSmi(receiver), &throw_bad_receiver);
- GotoIfNot(IsJSTypedArray(CAST(receiver)), &throw_bad_receiver);
-
- // Check if the {receiver}'s JSArrayBuffer was detached.
- ThrowIfArrayBufferViewBufferIsDetached(context, CAST(receiver), method_name);
-
- Return(CreateArrayIterator(context, receiver, kind));
-
- BIND(&throw_bad_receiver);
- ThrowTypeError(context, MessageTemplate::kNotTypedArray, method_name);
-}
-
-// ES #sec-%typedarray%.prototype.values
-TF_BUILTIN(TypedArrayPrototypeValues, TypedArrayBuiltinsAssembler) {
- TNode<Context> context = CAST(Parameter(Descriptor::kContext));
- TNode<Object> receiver = CAST(Parameter(Descriptor::kReceiver));
- GenerateTypedArrayPrototypeIterationMethod(context, receiver,
- "%TypedArray%.prototype.values()",
- IterationKind::kValues);
-}
-
-// ES #sec-%typedarray%.prototype.entries
-TF_BUILTIN(TypedArrayPrototypeEntries, TypedArrayBuiltinsAssembler) {
- TNode<Context> context = CAST(Parameter(Descriptor::kContext));
- TNode<Object> receiver = CAST(Parameter(Descriptor::kReceiver));
- GenerateTypedArrayPrototypeIterationMethod(context, receiver,
- "%TypedArray%.prototype.entries()",
- IterationKind::kEntries);
-}
-
-// ES #sec-%typedarray%.prototype.keys
-TF_BUILTIN(TypedArrayPrototypeKeys, TypedArrayBuiltinsAssembler) {
- TNode<Context> context = CAST(Parameter(Descriptor::kContext));
- TNode<Object> receiver = CAST(Parameter(Descriptor::kReceiver));
- GenerateTypedArrayPrototypeIterationMethod(
- context, receiver, "%TypedArray%.prototype.keys()", IterationKind::kKeys);
-}
-
} // namespace internal
} // namespace v8
diff --git a/chromium/v8/src/builtins/builtins-typed-array-gen.h b/chromium/v8/src/builtins/builtins-typed-array-gen.h
index 1008b6bdd73..7b725ffc41f 100644
--- a/chromium/v8/src/builtins/builtins-typed-array-gen.h
+++ b/chromium/v8/src/builtins/builtins-typed-array-gen.h
@@ -16,11 +16,6 @@ class TypedArrayBuiltinsAssembler : public CodeStubAssembler {
explicit TypedArrayBuiltinsAssembler(compiler::CodeAssemblerState* state)
: CodeStubAssembler(state) {}
- void GenerateTypedArrayPrototypeIterationMethod(TNode<Context> context,
- TNode<Object> receiver,
- const char* method_name,
- IterationKind iteration_kind);
-
void SetupTypedArrayEmbedderFields(TNode<JSTypedArray> holder);
void AttachBuffer(TNode<JSTypedArray> holder, TNode<JSArrayBuffer> buffer,
TNode<Map> map, TNode<Smi> length,
diff --git a/chromium/v8/src/builtins/builtins-wasm-gen.cc b/chromium/v8/src/builtins/builtins-wasm-gen.cc
index 28efa39c67d..1932db3ff40 100644
--- a/chromium/v8/src/builtins/builtins-wasm-gen.cc
+++ b/chromium/v8/src/builtins/builtins-wasm-gen.cc
@@ -37,12 +37,10 @@ TNode<FixedArray> WasmBuiltinsAssembler::LoadExternalFunctionsFromInstance(
instance, WasmInstanceObject::kWasmExternalFunctionsOffset);
}
-TNode<Smi> WasmBuiltinsAssembler::SmiFromUint32WithSaturation(
- TNode<Uint32T> value, uint32_t max) {
- DCHECK_LE(max, static_cast<uint32_t>(Smi::kMaxValue));
- TNode<Uint32T> capped_value = SelectConstant(
- Uint32LessThan(value, Uint32Constant(max)), value, Uint32Constant(max));
- return SmiFromUint32(capped_value);
+TNode<FixedArray> WasmBuiltinsAssembler::LoadManagedObjectMapsFromInstance(
+ TNode<WasmInstanceObject> instance) {
+ return LoadObjectField<FixedArray>(
+ instance, WasmInstanceObject::kManagedObjectMapsOffset);
}
TF_BUILTIN(WasmFloat32ToNumber, WasmBuiltinsAssembler) {
@@ -55,22 +53,6 @@ TF_BUILTIN(WasmFloat64ToNumber, WasmBuiltinsAssembler) {
Return(ChangeFloat64ToTagged(val));
}
-TF_BUILTIN(WasmAtomicNotify, WasmBuiltinsAssembler) {
- TNode<Uint32T> address =
- UncheckedCast<Uint32T>(Parameter(Descriptor::kAddress));
- TNode<Uint32T> count = UncheckedCast<Uint32T>(Parameter(Descriptor::kCount));
-
- TNode<WasmInstanceObject> instance = LoadInstanceFromFrame();
- TNode<Number> address_number = ChangeUint32ToTagged(address);
- TNode<Number> count_number = ChangeUint32ToTagged(count);
- TNode<Context> context = LoadContextFromInstance(instance);
-
- TNode<Smi> result_smi =
- CAST(CallRuntime(Runtime::kWasmAtomicNotify, context, instance,
- address_number, count_number));
- Return(Unsigned(SmiToInt32(result_smi)));
-}
-
TF_BUILTIN(WasmI32AtomicWait32, WasmBuiltinsAssembler) {
if (!Is32()) {
Unreachable();
@@ -100,33 +82,6 @@ TF_BUILTIN(WasmI32AtomicWait32, WasmBuiltinsAssembler) {
Return(Unsigned(SmiToInt32(result_smi)));
}
-TF_BUILTIN(WasmI32AtomicWait64, WasmBuiltinsAssembler) {
- if (!Is64()) {
- Unreachable();
- return;
- }
-
- TNode<Uint32T> address =
- UncheckedCast<Uint32T>(Parameter(Descriptor::kAddress));
- TNode<Number> address_number = ChangeUint32ToTagged(address);
-
- TNode<Int32T> expected_value =
- UncheckedCast<Int32T>(Parameter(Descriptor::kExpectedValue));
- TNode<Number> expected_value_number = ChangeInt32ToTagged(expected_value);
-
- TNode<IntPtrT> timeout_raw =
- UncheckedCast<IntPtrT>(Parameter(Descriptor::kTimeout));
- TNode<BigInt> timeout = BigIntFromInt64(timeout_raw);
-
- TNode<WasmInstanceObject> instance = LoadInstanceFromFrame();
- TNode<Context> context = LoadContextFromInstance(instance);
-
- TNode<Smi> result_smi =
- CAST(CallRuntime(Runtime::kWasmI32AtomicWait, context, instance,
- address_number, expected_value_number, timeout));
- Return(Unsigned(SmiToInt32(result_smi)));
-}
-
TF_BUILTIN(WasmI64AtomicWait32, WasmBuiltinsAssembler) {
if (!Is32()) {
Unreachable();
@@ -159,93 +114,6 @@ TF_BUILTIN(WasmI64AtomicWait32, WasmBuiltinsAssembler) {
Return(Unsigned(SmiToInt32(result_smi)));
}
-TF_BUILTIN(WasmI64AtomicWait64, WasmBuiltinsAssembler) {
- if (!Is64()) {
- Unreachable();
- return;
- }
-
- TNode<Uint32T> address =
- UncheckedCast<Uint32T>(Parameter(Descriptor::kAddress));
- TNode<Number> address_number = ChangeUint32ToTagged(address);
-
- TNode<IntPtrT> expected_value_raw =
- UncheckedCast<IntPtrT>(Parameter(Descriptor::kExpectedValue));
- TNode<BigInt> expected_value = BigIntFromInt64(expected_value_raw);
-
- TNode<IntPtrT> timeout_raw =
- UncheckedCast<IntPtrT>(Parameter(Descriptor::kTimeout));
- TNode<BigInt> timeout = BigIntFromInt64(timeout_raw);
-
- TNode<WasmInstanceObject> instance = LoadInstanceFromFrame();
- TNode<Context> context = LoadContextFromInstance(instance);
-
- TNode<Smi> result_smi =
- CAST(CallRuntime(Runtime::kWasmI64AtomicWait, context, instance,
- address_number, expected_value, timeout));
- Return(Unsigned(SmiToInt32(result_smi)));
-}
-
-TF_BUILTIN(WasmTableInit, WasmBuiltinsAssembler) {
- TNode<Uint32T> dst_raw =
- UncheckedCast<Uint32T>(Parameter(Descriptor::kDestination));
- // We cap {dst}, {src}, and {size} by {wasm::kV8MaxWasmTableSize + 1} to make
- // sure that the values fit into a Smi.
- STATIC_ASSERT(static_cast<size_t>(Smi::kMaxValue) >=
- wasm::kV8MaxWasmTableSize + 1);
- constexpr uint32_t kCap =
- static_cast<uint32_t>(wasm::kV8MaxWasmTableSize + 1);
- TNode<Smi> dst = SmiFromUint32WithSaturation(dst_raw, kCap);
- TNode<Uint32T> src_raw =
- UncheckedCast<Uint32T>(Parameter(Descriptor::kSource));
- TNode<Smi> src = SmiFromUint32WithSaturation(src_raw, kCap);
- TNode<Uint32T> size_raw =
- UncheckedCast<Uint32T>(Parameter(Descriptor::kSize));
- TNode<Smi> size = SmiFromUint32WithSaturation(size_raw, kCap);
- TNode<Smi> table_index =
- UncheckedCast<Smi>(Parameter(Descriptor::kTableIndex));
- TNode<Smi> segment_index =
- UncheckedCast<Smi>(Parameter(Descriptor::kSegmentIndex));
- TNode<WasmInstanceObject> instance = LoadInstanceFromFrame();
- TNode<Context> context = LoadContextFromInstance(instance);
-
- TailCallRuntime(Runtime::kWasmTableInit, context, instance, table_index,
- segment_index, dst, src, size);
-}
-
-TF_BUILTIN(WasmTableCopy, WasmBuiltinsAssembler) {
- // We cap {dst}, {src}, and {size} by {wasm::kV8MaxWasmTableSize + 1} to make
- // sure that the values fit into a Smi.
- STATIC_ASSERT(static_cast<size_t>(Smi::kMaxValue) >=
- wasm::kV8MaxWasmTableSize + 1);
- constexpr uint32_t kCap =
- static_cast<uint32_t>(wasm::kV8MaxWasmTableSize + 1);
-
- TNode<Uint32T> dst_raw =
- UncheckedCast<Uint32T>(Parameter(Descriptor::kDestination));
- TNode<Smi> dst = SmiFromUint32WithSaturation(dst_raw, kCap);
-
- TNode<Uint32T> src_raw =
- UncheckedCast<Uint32T>(Parameter(Descriptor::kSource));
- TNode<Smi> src = SmiFromUint32WithSaturation(src_raw, kCap);
-
- TNode<Uint32T> size_raw =
- UncheckedCast<Uint32T>(Parameter(Descriptor::kSize));
- TNode<Smi> size = SmiFromUint32WithSaturation(size_raw, kCap);
-
- TNode<Smi> dst_table =
- UncheckedCast<Smi>(Parameter(Descriptor::kDestinationTable));
-
- TNode<Smi> src_table =
- UncheckedCast<Smi>(Parameter(Descriptor::kSourceTable));
-
- TNode<WasmInstanceObject> instance = LoadInstanceFromFrame();
- TNode<Context> context = LoadContextFromInstance(instance);
-
- TailCallRuntime(Runtime::kWasmTableCopy, context, instance, dst_table,
- src_table, dst, src, size);
-}
-
TF_BUILTIN(WasmAllocateArray, WasmBuiltinsAssembler) {
TNode<WasmInstanceObject> instance = LoadInstanceFromFrame();
TNode<Smi> map_index = CAST(Parameter(Descriptor::kMapIndex));
@@ -270,18 +138,5 @@ TF_BUILTIN(WasmAllocateArray, WasmBuiltinsAssembler) {
Return(result);
}
-TF_BUILTIN(WasmAllocateStruct, WasmBuiltinsAssembler) {
- TNode<WasmInstanceObject> instance = LoadInstanceFromFrame();
- TNode<Smi> map_index = CAST(Parameter(Descriptor::kMapIndex));
- TNode<FixedArray> maps_list = LoadObjectField<FixedArray>(
- instance, WasmInstanceObject::kManagedObjectMapsOffset);
- TNode<Map> map = CAST(LoadFixedArrayElement(maps_list, map_index));
- TNode<IntPtrT> instance_size =
- TimesTaggedSize(LoadMapInstanceSizeInWords(map));
- TNode<WasmStruct> result = UncheckedCast<WasmStruct>(Allocate(instance_size));
- StoreMap(result, map);
- Return(result);
-}
-
} // namespace internal
} // namespace v8
diff --git a/chromium/v8/src/builtins/builtins-wasm-gen.h b/chromium/v8/src/builtins/builtins-wasm-gen.h
index 3740560666d..ccf5bae7a15 100644
--- a/chromium/v8/src/builtins/builtins-wasm-gen.h
+++ b/chromium/v8/src/builtins/builtins-wasm-gen.h
@@ -25,8 +25,8 @@ class WasmBuiltinsAssembler : public CodeStubAssembler {
TNode<FixedArray> LoadExternalFunctionsFromInstance(
TNode<WasmInstanceObject> instance);
- protected:
- TNode<Smi> SmiFromUint32WithSaturation(TNode<Uint32T> value, uint32_t max);
+ TNode<FixedArray> LoadManagedObjectMapsFromInstance(
+ TNode<WasmInstanceObject> instance);
};
} // namespace internal
diff --git a/chromium/v8/src/builtins/cast.tq b/chromium/v8/src/builtins/cast.tq
index dfac2035784..9adbd7ecc4f 100644
--- a/chromium/v8/src/builtins/cast.tq
+++ b/chromium/v8/src/builtins/cast.tq
@@ -2,56 +2,28 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-extern macro IsAllocationSite(HeapObject): bool;
extern macro IsBigInt(HeapObject): bool;
extern macro IsConstructor(HeapObject): bool;
extern macro IsContext(HeapObject): bool;
extern macro IsCustomElementsReceiverInstanceType(int32): bool;
extern macro IsExtensibleMap(Map): bool;
-extern macro IsFeedbackCell(HeapObject): bool;
-extern macro IsFeedbackVector(HeapObject): bool;
extern macro IsFixedArray(HeapObject): bool;
extern macro IsHeapNumber(HeapObject): bool;
-extern macro IsJSAggregateError(HeapObject): bool;
-extern macro IsJSArray(HeapObject): bool;
extern macro IsJSArrayMap(Map): bool;
-extern macro IsJSBoundFunction(HeapObject): bool;
-extern macro IsJSFinalizationRegistry(HeapObject): bool;
-extern macro IsJSFunction(HeapObject): bool;
-extern macro IsJSObject(HeapObject): bool;
-extern macro IsJSPrimitiveWrapper(HeapObject): bool;
-extern macro IsJSPromise(HeapObject): bool;
extern macro IsJSProxy(HeapObject): bool;
-extern macro IsJSReceiver(HeapObject): bool;
-extern macro IsJSRegExp(HeapObject): bool;
-extern macro IsJSRegExpStringIterator(HeapObject): bool;
-extern macro IsJSTypedArray(HeapObject): bool;
-extern macro IsMap(HeapObject): bool;
extern macro IsName(HeapObject): bool;
extern macro IsNativeContext(HeapObject): bool;
-extern macro IsNumberDictionary(HeapObject): bool;
extern macro IsNumberNormalized(Number): bool;
extern macro IsNumber(Object): bool;
-extern macro IsOddball(HeapObject): bool;
extern macro IsPrivateSymbol(HeapObject): bool;
-extern macro IsPromiseCapability(HeapObject): bool;
-extern macro IsPromiseFulfillReactionJobTask(HeapObject): bool;
-extern macro IsPromiseReaction(HeapObject): bool;
-extern macro IsPromiseReactionJobTask(HeapObject): bool;
-extern macro IsPromiseRejectReactionJobTask(HeapObject): bool;
extern macro IsSafeInteger(Object): bool;
-extern macro IsSharedFunctionInfo(HeapObject): bool;
-extern macro IsSymbol(HeapObject): bool;
-extern macro IsTuple2(HeapObject): bool;
-extern macro HeapObjectToJSDataView(HeapObject): JSDataView
- labels CastError;
-extern macro HeapObjectToJSProxy(HeapObject): JSProxy
- labels CastError;
-extern macro HeapObjectToJSStringIterator(HeapObject): JSStringIterator
- labels CastError;
-extern macro HeapObjectToJSArrayBuffer(HeapObject): JSArrayBuffer
- labels CastError;
+@export
+macro IsAllocationSite(o: HeapObject): bool {
+ Cast<AllocationSite>(o) otherwise return false;
+ return true;
+}
+
extern macro TaggedToHeapObject(Object): HeapObject
labels CastError;
extern macro TaggedToSmi(Object): Smi
@@ -60,28 +32,13 @@ extern macro TaggedToPositiveSmi(Object): PositiveSmi
labels CastError;
extern macro TaggedToDirectString(Object): DirectString
labels CastError;
-extern macro HeapObjectToJSAggregateError(HeapObject): JSAggregateError
- labels CastError;
-extern macro HeapObjectToJSArray(HeapObject): JSArray
- labels CastError;
extern macro HeapObjectToCallable(HeapObject): Callable
labels CastError;
-extern macro HeapObjectToFixedArray(HeapObject): FixedArray
- labels CastError;
-extern macro HeapObjectToFixedDoubleArray(HeapObject): FixedDoubleArray
- labels CastError;
-extern macro HeapObjectToString(HeapObject): String
- labels CastError;
extern macro HeapObjectToConstructor(HeapObject): Constructor
labels CastError;
extern macro HeapObjectToJSFunctionWithPrototypeSlot(HeapObject):
JSFunctionWithPrototypeSlot
labels CastError;
-extern macro HeapObjectToHeapNumber(HeapObject): HeapNumber
- labels CastError;
-extern macro HeapObjectToSloppyArgumentsElements(HeapObject):
- SloppyArgumentsElements
- labels CastError;
extern macro TaggedToNumber(Object): Number
labels CastError;
@@ -90,7 +47,17 @@ macro Cast<A : type extends WeakHeapObject>(o: A|Object): A labels CastError {
return %RawDownCast<A>(o);
}
-macro Cast<A: type>(o: MaybeObject): A labels CastError;
+macro Cast<A : type extends Object>(implicit context: Context)(o: MaybeObject):
+ A labels CastError {
+ typeswitch (o) {
+ case (WeakHeapObject): {
+ goto CastError;
+ }
+ case (o: Object): {
+ return Cast<A>(o) otherwise CastError;
+ }
+ }
+}
Cast<Undefined>(o: MaybeObject): Undefined labels CastError {
if (TaggedNotEqual(o, Undefined)) goto CastError;
@@ -283,22 +250,6 @@ Cast<Undefined>(o: HeapObject): Undefined
return Cast<Undefined>(o) otherwise CastError;
}
-Cast<AllocationSite>(o: HeapObject): AllocationSite
- labels CastError {
- if (IsAllocationSite(o)) return %RawDownCast<AllocationSite>(o);
- goto CastError;
-}
-
-Cast<FixedArray>(o: HeapObject): FixedArray
- labels CastError {
- return HeapObjectToFixedArray(o) otherwise CastError;
-}
-
-Cast<FixedDoubleArray>(o: HeapObject): FixedDoubleArray
- labels CastError {
- return HeapObjectToFixedDoubleArray(o) otherwise CastError;
-}
-
Cast<EmptyFixedArray>(o: Object): EmptyFixedArray
labels CastError {
if (o != kEmptyFixedArray) goto CastError;
@@ -325,46 +276,6 @@ Cast<(FixedDoubleArray | EmptyFixedArray)>(o: HeapObject): FixedDoubleArray|
}
}
-Cast<SloppyArgumentsElements>(o: HeapObject): SloppyArgumentsElements
- labels CastError {
- return HeapObjectToSloppyArgumentsElements(o) otherwise CastError;
-}
-
-Cast<JSDataView>(o: HeapObject): JSDataView
- labels CastError {
- return HeapObjectToJSDataView(o) otherwise CastError;
-}
-
-Cast<JSProxy>(o: HeapObject): JSProxy
- labels CastError {
- return HeapObjectToJSProxy(o) otherwise CastError;
-}
-
-Cast<JSStringIterator>(o: HeapObject): JSStringIterator
- labels CastError {
- return HeapObjectToJSStringIterator(o) otherwise CastError;
-}
-
-Cast<JSRegExpStringIterator>(o: HeapObject): JSRegExpStringIterator
- labels CastError {
- if (IsJSRegExpStringIterator(o)) {
- return %RawDownCast<JSRegExpStringIterator>(o);
- }
- goto CastError;
-}
-
-Cast<JSTypedArray>(o: HeapObject): JSTypedArray
- labels CastError {
- if (IsJSTypedArray(o)) return %RawDownCast<JSTypedArray>(o);
- goto CastError;
-}
-
-Cast<JSTypedArray>(implicit context: Context)(o: Object): JSTypedArray
- labels CastError {
- const heapObject = Cast<HeapObject>(o) otherwise CastError;
- return Cast<JSTypedArray>(heapObject) otherwise CastError;
-}
-
Cast<Callable>(o: HeapObject): Callable
labels CastError {
return HeapObjectToCallable(o) otherwise CastError;
@@ -376,62 +287,6 @@ Cast<Undefined|Callable>(o: HeapObject): Undefined|Callable
return HeapObjectToCallable(o) otherwise CastError;
}
-Cast<JSAggregateError>(o: HeapObject): JSAggregateError
- labels CastError {
- return HeapObjectToJSAggregateError(o) otherwise CastError;
-}
-
-Cast<JSArray>(o: HeapObject): JSArray
- labels CastError {
- return HeapObjectToJSArray(o) otherwise CastError;
-}
-
-Cast<JSArrayBuffer>(o: HeapObject): JSArrayBuffer
- labels CastError {
- return HeapObjectToJSArrayBuffer(o) otherwise CastError;
-}
-
-Cast<Context>(o: HeapObject): Context
- labels CastError {
- if (IsContext(o)) return %RawDownCast<Context>(o);
- goto CastError;
-}
-
-Cast<NativeContext>(o: HeapObject): NativeContext
- labels CastError {
- if (IsNativeContext(o)) return %RawDownCast<NativeContext>(o);
- goto CastError;
-}
-
-Cast<JSObject>(o: HeapObject): JSObject
- labels CastError {
- if (IsJSObject(o)) return %RawDownCast<JSObject>(o);
- goto CastError;
-}
-
-Cast<NumberDictionary>(o: HeapObject): NumberDictionary
- labels CastError {
- if (IsNumberDictionary(o)) return %RawDownCast<NumberDictionary>(o);
- goto CastError;
-}
-
-Cast<String>(o: HeapObject): String
- labels CastError {
- return HeapObjectToString(o) otherwise CastError;
-}
-
-Cast<Oddball>(o: HeapObject): Oddball
- labels CastError {
- if (IsOddball(o)) return %RawDownCast<Oddball>(o);
- goto CastError;
-}
-
-Cast<Symbol>(o: HeapObject): Symbol
- labels CastError {
- if (IsSymbol(o)) return %RawDownCast<Symbol>(o);
- goto CastError;
-}
-
macro Cast<T : type extends Symbol>(o: Symbol): T labels CastError;
Cast<PublicSymbol>(o: Symbol): PublicSymbol labels CastError {
if (IsPrivateSymbol(o)) goto CastError;
@@ -468,53 +323,17 @@ Cast<JSFunctionWithPrototypeSlot>(o: HeapObject): JSFunctionWithPrototypeSlot
return HeapObjectToJSFunctionWithPrototypeSlot(o) otherwise CastError;
}
-Cast<HeapNumber>(o: HeapObject): HeapNumber
- labels CastError {
- if (IsHeapNumber(o)) return %RawDownCast<HeapNumber>(o);
- goto CastError;
-}
-
Cast<BigInt>(o: HeapObject): BigInt labels CastError {
if (IsBigInt(o)) return %RawDownCast<BigInt>(o);
goto CastError;
}
-Cast<JSRegExp>(o: HeapObject): JSRegExp
- labels CastError {
- if (IsJSRegExp(o)) return %RawDownCast<JSRegExp>(o);
- goto CastError;
-}
-
Cast<JSRegExpResult>(implicit context: Context)(o: HeapObject): JSRegExpResult
labels CastError {
if (regexp::IsRegExpResult(o)) return %RawDownCast<JSRegExpResult>(o);
goto CastError;
}
-Cast<Map>(implicit context: Context)(o: HeapObject): Map
- labels CastError {
- if (IsMap(o)) return %RawDownCast<Map>(o);
- goto CastError;
-}
-
-Cast<FeedbackCell>(implicit context: Context)(o: HeapObject): FeedbackCell
- labels CastError {
- if (IsFeedbackCell(o)) return %RawDownCast<FeedbackCell>(o);
- goto CastError;
-}
-
-Cast<FeedbackVector>(implicit context: Context)(o: HeapObject): FeedbackVector
- labels CastError {
- if (IsFeedbackVector(o)) return %RawDownCast<FeedbackVector>(o);
- goto CastError;
-}
-
-Cast<JSPrimitiveWrapper>(o: HeapObject): JSPrimitiveWrapper
- labels CastError {
- if (IsJSPrimitiveWrapper(o)) return %RawDownCast<JSPrimitiveWrapper>(o);
- goto CastError;
-}
-
Cast<JSSloppyArgumentsObject>(implicit context: Context)(o: HeapObject):
JSSloppyArgumentsObject
labels CastError {
@@ -623,32 +442,6 @@ Cast<FastJSArrayForReadWithNoCustomIteration>(implicit context: Context)(
return %RawDownCast<FastJSArrayForReadWithNoCustomIteration>(a);
}
-Cast<JSReceiver>(o: HeapObject): JSReceiver
- labels CastError {
- if (IsJSReceiver(o)) return %RawDownCast<JSReceiver>(o);
- goto CastError;
-}
-
-Cast<JSFunction>(implicit context: Context)(o: HeapObject): JSFunction
- labels CastError {
- if (IsJSFunction(o)) return %RawDownCast<JSFunction>(o);
- goto CastError;
-}
-
-extern macro IsDebugInfo(HeapObject): bool;
-Cast<DebugInfo>(implicit context: Context)(o: HeapObject): DebugInfo
- labels CastError {
- if (IsDebugInfo(o)) return %RawDownCast<DebugInfo>(o);
- goto CastError;
-}
-
-extern macro IsCoverageInfo(HeapObject): bool;
-Cast<CoverageInfo>(implicit context: Context)(o: HeapObject): CoverageInfo
- labels CastError {
- if (IsCoverageInfo(o)) return %RawDownCast<CoverageInfo>(o);
- goto CastError;
-}
-
Cast<JSReceiver|Null>(o: HeapObject): JSReceiver|Null
labels CastError {
typeswitch (o) {
@@ -664,35 +457,6 @@ Cast<JSReceiver|Null>(o: HeapObject): JSReceiver|Null
}
}
-Cast<PromiseReactionJobTask>(o: HeapObject):
- PromiseReactionJobTask labels CastError {
- if (IsPromiseReactionJobTask(o)) {
- return %RawDownCast<PromiseReactionJobTask>(o);
- }
- goto CastError;
-}
-
-Cast<PromiseFulfillReactionJobTask>(o: HeapObject):
- PromiseFulfillReactionJobTask labels CastError {
- if (IsPromiseFulfillReactionJobTask(o)) {
- return %RawDownCast<PromiseFulfillReactionJobTask>(o);
- }
- goto CastError;
-}
-
-Cast<PromiseRejectReactionJobTask>(o: HeapObject):
- PromiseRejectReactionJobTask labels CastError {
- if (IsPromiseRejectReactionJobTask(o)) {
- return %RawDownCast<PromiseRejectReactionJobTask>(o);
- }
- goto CastError;
-}
-
-Cast<PromiseReaction>(o: HeapObject): PromiseReaction labels CastError {
- if (IsPromiseReaction(o)) return %RawDownCast<PromiseReaction>(o);
- goto CastError;
-}
-
Cast<Smi|PromiseReaction>(o: Object): Smi|PromiseReaction labels CastError {
typeswitch (o) {
case (o: Smi): {
@@ -737,32 +501,35 @@ Cast<Zero|PromiseReaction>(implicit context: Context)(o: Object): Zero|
}
}
-Cast<JSBoundFunction>(o: HeapObject): JSBoundFunction labels CastError {
- if (IsJSBoundFunction(o)) return %RawDownCast<JSBoundFunction>(o);
- goto CastError;
-}
-
-Cast<PromiseCapability>(o: HeapObject): PromiseCapability labels CastError {
- if (IsPromiseCapability(o)) return %RawDownCast<PromiseCapability>(o);
- goto CastError;
+Cast<JSFunction|JSBoundFunction>(implicit context: Context)(o: Object):
+ JSFunction|JSBoundFunction labels CastError {
+ typeswitch (o) {
+ case (o: JSFunction): {
+ return o;
+ }
+ case (o: JSBoundFunction): {
+ return o;
+ }
+ case (Object): {
+ goto CastError;
+ }
+ }
}
-Cast<SharedFunctionInfo>(o: HeapObject): SharedFunctionInfo labels CastError {
- if (IsSharedFunctionInfo(o)) return %RawDownCast<SharedFunctionInfo>(o);
- goto CastError;
+macro Is<A : type extends Object, B : type extends Object>(
+ implicit context: Context)(o: B): bool {
+ Cast<A>(o) otherwise return false;
+ return true;
}
-Cast<JSPromise>(o: HeapObject): JSPromise labels CastError {
- if (IsJSPromise(o)) return %RawDownCast<JSPromise>(o);
- goto CastError;
+macro UnsafeCast<A : type extends Object>(implicit context: Context)(o: Object):
+ A {
+ assert(Is<A>(o));
+ return %RawDownCast<A>(o);
}
-Cast<JSFinalizationRegistry>(o: HeapObject):
- JSFinalizationRegistry labels CastError {
- if (IsJSFinalizationRegistry(o)) {
- return %RawDownCast<JSFinalizationRegistry>(o);
- }
- goto CastError;
+macro UnsafeConstCast<T: type>(r: const &T):&T {
+ return %RawDownCast<&T>(r);
}
UnsafeCast<RegExpMatchInfo>(implicit context: Context)(o: Object):
diff --git a/chromium/v8/src/builtins/constants-table-builder.cc b/chromium/v8/src/builtins/constants-table-builder.cc
index 94e8dc05ec7..fa333726e79 100644
--- a/chromium/v8/src/builtins/constants-table-builder.cc
+++ b/chromium/v8/src/builtins/constants-table-builder.cc
@@ -57,24 +57,30 @@ uint32_t BuiltinsConstantsTableBuilder::AddObject(Handle<Object> object) {
}
}
-void BuiltinsConstantsTableBuilder::PatchSelfReference(
- Handle<Object> self_reference, Handle<Code> code_object) {
-#ifdef DEBUG
+namespace {
+void CheckPreconditionsForPatching(Isolate* isolate,
+ Handle<Object> replacement_object) {
// Roots must not be inserted into the constants table as they are already
- // accessibly from the root list.
+ // accessible from the root list.
RootIndex root_list_index;
- DCHECK(!isolate_->roots_table().IsRootHandle(code_object, &root_list_index));
+ DCHECK(!isolate->roots_table().IsRootHandle(replacement_object,
+ &root_list_index));
+ USE(root_list_index);
// Not yet finalized.
- DCHECK_EQ(ReadOnlyRoots(isolate_).empty_fixed_array(),
- isolate_->heap()->builtins_constants_table());
+ DCHECK_EQ(ReadOnlyRoots(isolate).empty_fixed_array(),
+ isolate->heap()->builtins_constants_table());
- DCHECK(isolate_->IsGeneratingEmbeddedBuiltins());
+ DCHECK(isolate->IsGeneratingEmbeddedBuiltins());
+}
+} // namespace
+void BuiltinsConstantsTableBuilder::PatchSelfReference(
+ Handle<Object> self_reference, Handle<Code> code_object) {
+ CheckPreconditionsForPatching(isolate_, code_object);
DCHECK(self_reference->IsOddball());
DCHECK(Oddball::cast(*self_reference).kind() ==
Oddball::kSelfReferenceMarker);
-#endif
uint32_t key;
if (map_.Delete(self_reference, &key)) {
@@ -83,6 +89,17 @@ void BuiltinsConstantsTableBuilder::PatchSelfReference(
}
}
+void BuiltinsConstantsTableBuilder::PatchBasicBlockCountersReference(
+ Handle<ByteArray> counters) {
+ CheckPreconditionsForPatching(isolate_, counters);
+
+ uint32_t key;
+ if (map_.Delete(ReadOnlyRoots(isolate_).basic_block_counters_marker(),
+ &key)) {
+ map_.Set(counters, key);
+ }
+}
+
void BuiltinsConstantsTableBuilder::Finalize() {
HandleScope handle_scope(isolate_);
@@ -117,6 +134,8 @@ void BuiltinsConstantsTableBuilder::Finalize() {
DCHECK(table->get(i).IsHeapObject());
DCHECK_NE(ReadOnlyRoots(isolate_).undefined_value(), table->get(i));
DCHECK_NE(ReadOnlyRoots(isolate_).self_reference_marker(), table->get(i));
+ DCHECK_NE(ReadOnlyRoots(isolate_).basic_block_counters_marker(),
+ table->get(i));
}
#endif
diff --git a/chromium/v8/src/builtins/constants-table-builder.h b/chromium/v8/src/builtins/constants-table-builder.h
index 89c95912a1e..fa9d7dee3a3 100644
--- a/chromium/v8/src/builtins/constants-table-builder.h
+++ b/chromium/v8/src/builtins/constants-table-builder.h
@@ -34,6 +34,11 @@ class BuiltinsConstantsTableBuilder final {
void PatchSelfReference(Handle<Object> self_reference,
Handle<Code> code_object);
+ // References to the array that stores basic block usage counters start out as
+ // references to a unique oddball. Once the actual array has been allocated,
+ // such entries in the constants map must be patched up.
+ void PatchBasicBlockCountersReference(Handle<ByteArray> counters);
+
// Should be called after all affected code (e.g. builtins and bytecode
// handlers) has been generated.
void Finalize();
diff --git a/chromium/v8/src/builtins/conversion.tq b/chromium/v8/src/builtins/conversion.tq
new file mode 100644
index 00000000000..7f634d94905
--- /dev/null
+++ b/chromium/v8/src/builtins/conversion.tq
@@ -0,0 +1,232 @@
+// Copyright 2020 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+namespace runtime {
+extern transitioning runtime ToStringRT(Context, BigInt): String;
+}
+
+extern enum OrdinaryToPrimitiveHint { kString, kNumber }
+
+extern macro OrdinaryToPrimitive(implicit context: Context)(
+ JSAny, constexpr OrdinaryToPrimitiveHint): JSPrimitive;
+
+namespace conversion {
+
+builtin StringToNumber(implicit context: Context)(input: String): Number {
+ return ::StringToNumber(input);
+}
+
+transitioning builtin NonNumberToNumber(implicit context: Context)(
+ input: JSAnyNotNumber): Number {
+ return ::NonNumberToNumber(input);
+}
+
+transitioning builtin NonNumberToNumeric(implicit context: Context)(
+ input: JSAnyNotNumber): Numeric {
+ return ::NonNumberToNumeric(input);
+}
+
+transitioning builtin ToNumeric(implicit context: Context)(input: JSAny):
+ Numeric {
+ typeswitch (input) {
+ case (n: Number): {
+ return n;
+ }
+ case (h: JSAnyNotNumber): {
+ return conversion::NonNumberToNumeric(h);
+ }
+ }
+}
+
+// ES section #sec-tostring-applied-to-the-number-type
+builtin NumberToString(implicit context: Context)(input: Number): String {
+ return ::NumberToString(input);
+}
+
+// ES6 section 7.1.2 ToBoolean ( argument )
+builtin ToBoolean(implicit context: Context)(input: JSAny): Boolean {
+ BranchIfToBooleanIsTrue(input) otherwise return TrueConstant(),
+ return FalseConstant();
+}
+
+transitioning builtin ToLength(implicit context: Context)(input: JSAny):
+ Number {
+ // We might need to loop once for ToNumber conversion.
+ let x: JSAny = input;
+ while (true) {
+ typeswitch (x) {
+ case (s: Smi): {
+ if (s < 0) return 0;
+ return s;
+ }
+ case (h: HeapNumber): {
+ let value: float64 = Convert<float64>(h);
+ // The sense of this test is important for the NaN and -0 cases.
+ if (!(value > 0)) return 0;
+ if (value > kMaxSafeInteger) return kMaxSafeInteger;
+ value = math::Float64Floor(value);
+ return ChangeFloat64ToTagged(value);
+ }
+ case (h: JSAnyNotNumber): {
+ x = ::NonNumberToNumber(h);
+ }
+ }
+ }
+ VerifiedUnreachable();
+}
+
+transitioning builtin ToName(implicit context: Context)(input: JSAny): Name {
+ // We might need to loop once for ToNumber conversion.
+ let x: JSAny = input;
+ while (true) {
+ typeswitch (x) {
+ case (n: Name): {
+ return n;
+ }
+ case (n: Number): {
+ return ::NumberToString(n);
+ }
+ case (b: BigInt): {
+ // We don't have a fast-path for BigInt currently, so just
+ // tail call to the %ToString runtime function here for now.
+ tail runtime::ToStringRT(context, b);
+ }
+ case (o: Oddball): {
+ return o.to_string;
+ }
+ case (o: JSReceiver): {
+ x = NonPrimitiveToPrimitive_String(o);
+ }
+ }
+ }
+ VerifiedUnreachable();
+}
+
+const kNoConstructorFunctionIndex:
+ constexpr int31 generates 'Map::kNoConstructorFunctionIndex';
+
+// ES6 section 7.1.13 ToObject (argument)
+transitioning builtin ToObject(implicit context: Context)(input: JSAny):
+ JSReceiver {
+ try {
+ typeswitch (input) {
+ case (Smi): {
+ goto WrapPrimitive(NativeContextSlot::NUMBER_FUNCTION_INDEX);
+ }
+ case (o: JSReceiver): {
+ return o;
+ }
+ case (o: JSAnyNotSmi): {
+ const index: intptr = Convert<intptr>(
+ o.map.in_object_properties_start_or_constructor_function_index);
+ if (index != kNoConstructorFunctionIndex) goto WrapPrimitive(index);
+ ThrowTypeError(MessageTemplate::kUndefinedOrNullToObject, 'ToObject');
+ }
+ }
+ } label WrapPrimitive(constructorIndex: intptr) {
+ const nativeContext = LoadNativeContext(context);
+ const constructor = UnsafeCast<JSFunction>(nativeContext[constructorIndex]);
+ const map: Map = UnsafeCast<Map>(constructor.prototype_or_initial_map);
+ const wrapper =
+ UnsafeCast<JSPrimitiveWrapper>(AllocateFastOrSlowJSObjectFromMap(map));
+ wrapper.value = input;
+ return wrapper;
+ }
+}
+
+// ES6 section 7.1.1 ToPrimitive ( input [ , PreferredType ] )
+
+transitioning macro TryGetExoticToPrimitive(implicit context: Context)(
+ input: JSAny): JSAny labels OrdinaryToPrimitive {
+ // Look up the @@toPrimitive property.
+ const exoticToPrimitive: JSAny =
+ GetProperty(input, ToPrimitiveSymbolConstant());
+ if (IsNullOrUndefined(exoticToPrimitive)) goto OrdinaryToPrimitive;
+ return exoticToPrimitive;
+}
+
+transitioning macro CallExoticToPrimitive(implicit context: Context)(
+ input: JSAny, exoticToPrimitive: JSAny, hint: String): JSPrimitive {
+ // Invoke the exoticToPrimitive method on the input with a string
+ // representation of the hint.
+ const result: JSAny = Call(context, exoticToPrimitive, input, hint);
+
+ // Verify that the result is primitive.
+ typeswitch (result) {
+ case (o: JSPrimitive): {
+ return o;
+ }
+ case (JSReceiver): {
+ // Somehow the @@toPrimitive method on input didn't yield a primitive.
+ ThrowTypeError(MessageTemplate::kCannotConvertToPrimitive);
+ }
+ }
+}
+
+transitioning builtin NonPrimitiveToPrimitive_Default(
+ implicit context: Context)(input: JSReceiver): JSPrimitive {
+ const exoticToPrimitive: JSAny = TryGetExoticToPrimitive(input)
+ otherwise return OrdinaryToPrimitive_Number(input);
+ return CallExoticToPrimitive(
+ input, exoticToPrimitive, DefaultStringConstant());
+}
+
+transitioning builtin NonPrimitiveToPrimitive_Number(implicit context: Context)(
+ input: JSReceiver): JSPrimitive {
+ const exoticToPrimitive: JSAny = TryGetExoticToPrimitive(input)
+ otherwise return OrdinaryToPrimitive_Number(input);
+ return CallExoticToPrimitive(
+ input, exoticToPrimitive, NumberStringConstant());
+}
+
+transitioning builtin NonPrimitiveToPrimitive_String(implicit context: Context)(
+ input: JSReceiver): JSPrimitive {
+ const exoticToPrimitive: JSAny = TryGetExoticToPrimitive(input)
+ otherwise return OrdinaryToPrimitive_String(input);
+ return CallExoticToPrimitive(
+ input, exoticToPrimitive, StringStringConstant());
+}
+
+// 7.1.1.1 OrdinaryToPrimitive ( O, hint )
+
+transitioning macro TryToPrimitiveMethod(implicit context: Context)(
+ input: JSAny, name: String): JSPrimitive labels Continue {
+ const method: JSAny = GetProperty(input, name);
+ typeswitch (method) {
+ case (Callable): {
+ const value: JSAny = Call(context, method, input);
+ return Cast<JSPrimitive>(value) otherwise Continue;
+ }
+ case (JSAny): {
+ goto Continue;
+ }
+ }
+}
+
+transitioning builtin OrdinaryToPrimitive_Number(implicit context: Context)(
+ input: JSAny): JSPrimitive {
+ try {
+ return TryToPrimitiveMethod(input, ValueOfStringConstant())
+ otherwise String;
+ } label String {
+ return TryToPrimitiveMethod(input, ToStringStringConstant())
+ otherwise Throw;
+ } label Throw {
+ ThrowTypeError(MessageTemplate::kCannotConvertToPrimitive);
+ }
+}
+
+transitioning builtin OrdinaryToPrimitive_String(implicit context: Context)(
+ input: JSAny): JSPrimitive {
+ try {
+ return TryToPrimitiveMethod(input, ToStringStringConstant())
+ otherwise String;
+ } label String {
+ return TryToPrimitiveMethod(input, ValueOfStringConstant()) otherwise Throw;
+ } label Throw {
+ ThrowTypeError(MessageTemplate::kCannotConvertToPrimitive);
+ }
+}
+
+} // namespace conversion
diff --git a/chromium/v8/src/builtins/convert.tq b/chromium/v8/src/builtins/convert.tq
index e2c11120381..03440a183ad 100644
--- a/chromium/v8/src/builtins/convert.tq
+++ b/chromium/v8/src/builtins/convert.tq
@@ -94,6 +94,15 @@ FromConstexpr<PromiseState, constexpr PromiseState>(c: constexpr PromiseState):
PromiseState {
return %RawDownCast<PromiseState>(Int32Constant(c));
}
+FromConstexpr<InstanceType, constexpr InstanceType>(c: constexpr InstanceType):
+ InstanceType {
+ return %RawDownCast<InstanceType>(Uint16Constant(c));
+}
+
+FromConstexpr<IterationKind, constexpr IterationKind>(
+ c: constexpr IterationKind): IterationKind {
+ return %RawDownCast<IterationKind>(Unsigned(%FromConstexpr<int32>(c)));
+}
macro Convert<To: type, From: type>(i: From): To {
return i;
@@ -103,6 +112,9 @@ macro Convert<To: type, From: type>(i: From): To labels Overflow {
return i;
}
+Convert<Boolean, bool>(b: bool): Boolean {
+ return b ? True : False;
+}
extern macro ConvertElementsKindToInt(ElementsKind): int32;
Convert<int32, ElementsKind>(elementsKind: ElementsKind): int32 {
return ConvertElementsKindToInt(elementsKind);
@@ -201,6 +213,9 @@ Convert<PositiveSmi, intptr>(i: intptr): PositiveSmi labels IfOverflow {
goto IfOverflow;
}
}
+Convert<PositiveSmi, uint32>(ui: uint32): PositiveSmi labels IfOverflow {
+ return Convert<PositiveSmi>(Convert<uintptr>(ui)) otherwise IfOverflow;
+}
Convert<int32, Smi>(s: Smi): int32 {
return SmiToInt32(s);
}
diff --git a/chromium/v8/src/builtins/function.tq b/chromium/v8/src/builtins/function.tq
new file mode 100644
index 00000000000..8266714c7be
--- /dev/null
+++ b/chromium/v8/src/builtins/function.tq
@@ -0,0 +1,109 @@
+// Copyright 2020 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+namespace function {
+
+extern macro OrdinaryHasInstance(Context, Object, Object): JSAny;
+
+// ES6 section 19.2.3.6 Function.prototype[@@hasInstance]
+javascript builtin FunctionPrototypeHasInstance(
+ js-implicit context: NativeContext, receiver: JSAny)(value: JSAny): JSAny {
+ return OrdinaryHasInstance(context, receiver, value);
+}
+
+extern transitioning builtin
+FunctionPrototypeBind(implicit context: Context)(
+ JSFunction, JSAny, int32): JSAny;
+
+const kLengthDescriptorIndex:
+ constexpr int32 generates 'JSFunction::kLengthDescriptorIndex';
+const kNameDescriptorIndex:
+ constexpr int32 generates 'JSFunction::kNameDescriptorIndex';
+const kMinDescriptorsForFastBind:
+ constexpr int31 generates 'JSFunction::kMinDescriptorsForFastBind';
+
+macro CheckAccessor(implicit context: Context)(
+ array: DescriptorArray, index: constexpr int32, name: Name) labels Slow {
+ const descriptor: DescriptorEntry = array.descriptors[index];
+ const key: Name|Undefined = descriptor.key;
+ if (!TaggedEqual(key, name)) goto Slow;
+
+ // The descriptor value must be an AccessorInfo.
+ Cast<AccessorInfo>(descriptor.value) otherwise goto Slow;
+}
+
+// ES6 section 19.2.3.2 Function.prototype.bind
+transitioning javascript builtin
+FastFunctionPrototypeBind(
+ js-implicit context: NativeContext, receiver: JSAny, newTarget: JSAny,
+ target: JSFunction)(...arguments): JSAny {
+ const argc: intptr = arguments.length;
+ try {
+ typeswitch (receiver) {
+ case (fn: JSFunction|JSBoundFunction): {
+ // Disallow binding of slow-mode functions. We need to figure out
+ // whether the length and name property are in the original state.
+ Comment('Disallow binding of slow-mode functions');
+ if (IsDictionaryMap(fn.map)) goto Slow;
+
+ // Check whether the length and name properties are still present as
+ // AccessorInfo objects. If so, their value can be recomputed even if
+ // the actual value on the object changes.
+
+ if (fn.map.bit_field3.number_of_own_descriptors <
+ kMinDescriptorsForFastBind) {
+ goto Slow;
+ }
+
+ const descriptors: DescriptorArray = fn.map.instance_descriptors;
+ CheckAccessor(
+ descriptors, kLengthDescriptorIndex, LengthStringConstant())
+ otherwise Slow;
+ CheckAccessor(descriptors, kNameDescriptorIndex, NameStringConstant())
+ otherwise Slow;
+
+ // Choose the right bound function map based on whether the target is
+ // constructable.
+
+ const boundFunctionMap: Map = UnsafeCast<Map>(
+ IsConstructor(fn) ?
+ context[NativeContextSlot::
+ BOUND_FUNCTION_WITH_CONSTRUCTOR_MAP_INDEX] :
+ context[NativeContextSlot::
+ BOUND_FUNCTION_WITHOUT_CONSTRUCTOR_MAP_INDEX]);
+
+ // Verify that prototype matches that of the target bound function.
+
+ if (fn.map.prototype != boundFunctionMap.prototype) goto Slow;
+
+ // Allocate the arguments array.
+
+ const argumentsArray = arguments.length <= 1 ?
+ kEmptyFixedArray :
+ NewFixedArray(
+ arguments.length - 1, ArgumentsIterator{arguments, current: 1});
+
+ const boundReceiver: JSAny = arguments[0];
+
+ const result = new JSBoundFunction{
+ map: boundFunctionMap,
+ properties_or_hash: kEmptyFixedArray,
+ elements: kEmptyFixedArray,
+ bound_target_function: fn,
+ bound_this: boundReceiver,
+ bound_arguments: argumentsArray
+ };
+ return result;
+ }
+
+ case (JSAny): {
+ goto Slow;
+ }
+ }
+ } label Slow {
+ tail FunctionPrototypeBind(
+ LoadTargetFromFrame(), newTarget, Convert<int32>(argc));
+ }
+}
+} // namespace function
diff --git a/chromium/v8/src/builtins/growable-fixed-array.tq b/chromium/v8/src/builtins/growable-fixed-array.tq
index 094e051a65a..af9418b0c91 100644
--- a/chromium/v8/src/builtins/growable-fixed-array.tq
+++ b/chromium/v8/src/builtins/growable-fixed-array.tq
@@ -25,9 +25,6 @@ struct GrowableFixedArray {
this.array = this.ResizeFixedArray(this.capacity);
}
}
- macro ToFixedArray(): FixedArray {
- return this.ResizeFixedArray(this.length);
- }
macro ToJSArray(implicit context: Context)(): JSArray {
const nativeContext: NativeContext = LoadNativeContext(context);
diff --git a/chromium/v8/src/builtins/internal.tq b/chromium/v8/src/builtins/internal.tq
new file mode 100644
index 00000000000..9e7e4240ba2
--- /dev/null
+++ b/chromium/v8/src/builtins/internal.tq
@@ -0,0 +1,35 @@
+// Copyright 2020 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+namespace internal {
+
+namespace runtime {
+extern runtime GetTemplateObject(implicit context: Context)(
+ TemplateObjectDescription, SharedFunctionInfo, Smi): JSAny;
+}
+
+builtin GetTemplateObject(
+ context: Context, shared: SharedFunctionInfo,
+ description: TemplateObjectDescription, slot: uintptr,
+ maybeFeedbackVector: FeedbackVector|Undefined): JSArray {
+ // TODO(jgruber): Consider merging with the GetTemplateObject bytecode
+ // handler; the current advantage of the split implementation is that the
+ // bytecode can skip most work if feedback exists.
+
+ try {
+ const vector =
+ Cast<FeedbackVector>(maybeFeedbackVector) otherwise CallRuntime;
+ return Cast<JSArray>(ic::LoadFeedbackVectorSlot(vector, slot))
+ otherwise CallRuntime;
+ } label CallRuntime deferred {
+ const result = UnsafeCast<JSArray>(runtime::GetTemplateObject(
+ description, shared, Convert<Smi>(Signed(slot))));
+ const vector =
+ Cast<FeedbackVector>(maybeFeedbackVector) otherwise return result;
+ ic::StoreFeedbackVectorSlot(vector, slot, result);
+ return result;
+ }
+}
+
+} // namespace internal
diff --git a/chromium/v8/src/builtins/math.tq b/chromium/v8/src/builtins/math.tq
index 0586f432f5b..50bd3e2201b 100644
--- a/chromium/v8/src/builtins/math.tq
+++ b/chromium/v8/src/builtins/math.tq
@@ -4,9 +4,6 @@
namespace math {
-extern transitioning builtin
-NonNumberToNumber(implicit context: Context)(HeapObject): Number;
-
transitioning macro ReduceToSmiOrFloat64(implicit context: Context)(x: JSAny):
never
labels SmiResult(Smi), Float64Result(float64) {
@@ -20,7 +17,7 @@ transitioning macro ReduceToSmiOrFloat64(implicit context: Context)(x: JSAny):
goto Float64Result(Convert<float64>(h));
}
case (a: JSAnyNotNumber): {
- x1 = NonNumberToNumber(a);
+ x1 = conversion::NonNumberToNumber(a);
}
}
}
@@ -29,6 +26,7 @@ transitioning macro ReduceToSmiOrFloat64(implicit context: Context)(x: JSAny):
// ES6 #sec-math.abs
extern macro IsIntPtrAbsWithOverflowSupported(): constexpr bool;
+extern macro TrySmiAdd(Smi, Smi): Smi labels Overflow;
extern macro TrySmiSub(Smi, Smi): Smi labels Overflow;
extern macro TrySmiAbs(Smi): Smi labels Overflow;
extern macro Float64Abs(float64): float64;
diff --git a/chromium/v8/src/builtins/number.tq b/chromium/v8/src/builtins/number.tq
index 98680cf5533..753998424fa 100644
--- a/chromium/v8/src/builtins/number.tq
+++ b/chromium/v8/src/builtins/number.tq
@@ -2,9 +2,48 @@
// source code is governed by a BSD-style license that can be found in the
// LICENSE file.
+#include 'src/ic/binary-op-assembler.h'
+
+extern enum Operation extends uint31 {
+ // Binary operations.
+ kAdd,
+ kSubtract,
+ kMultiply,
+ kDivide,
+ kModulus,
+ kExponentiate,
+ kBitwiseAnd,
+ kBitwiseOr,
+ kBitwiseXor,
+ kShiftLeft,
+ kShiftRight,
+ kShiftRightLogical,
+ // Unary operations.
+ kBitwiseNot,
+ kNegate,
+ kIncrement,
+ kDecrement,
+ // Compare operations.
+ kEqual,
+ kStrictEqual,
+ kLessThan,
+ kLessThanOrEqual,
+ kGreaterThan,
+ kGreaterThanOrEqual
+}
+
namespace runtime {
extern transitioning runtime
DoubleToStringWithRadix(implicit context: Context)(Number, Number): String;
+
+extern transitioning runtime StringParseFloat(implicit context: Context)(
+ String): Number;
+extern transitioning runtime StringParseInt(implicit context: Context)(
+ JSAny, JSAny): Number;
+
+extern runtime BigIntUnaryOp(Context, BigInt, SmiTagged<Operation>): BigInt;
+extern runtime BigIntBinaryOp(
+ Context, Numeric, Numeric, SmiTagged<Operation>): BigInt;
} // namespace runtime
namespace number {
@@ -60,14 +99,649 @@ transitioning javascript builtin NumberPrototypeToString(
if (x == -0) {
return ZeroStringConstant();
- } else if (NumberIsNaN(x)) {
+ } else if (::NumberIsNaN(x)) {
return NaNStringConstant();
} else if (x == V8_INFINITY) {
return InfinityStringConstant();
} else if (x == MINUS_V8_INFINITY) {
return MinusInfinityStringConstant();
}
-
return runtime::DoubleToStringWithRadix(x, radixNumber);
}
+
+// ES6 #sec-number.isfinite
+javascript builtin NumberIsFinite(
+ js-implicit context: NativeContext,
+ receiver: JSAny)(value: JSAny): Boolean {
+ typeswitch (value) {
+ case (Smi): {
+ return True;
+ }
+ case (h: HeapNumber): {
+ const number: float64 = Convert<float64>(h);
+ const infiniteOrNaN: bool = Float64IsNaN(number - number);
+ return Convert<Boolean>(!infiniteOrNaN);
+ }
+ case (JSAnyNotNumber): {
+ return False;
+ }
+ }
+}
+
+// ES6 #sec-number.isinteger
+javascript builtin NumberIsInteger(js-implicit context: NativeContext)(
+ value: JSAny): Boolean {
+ return SelectBooleanConstant(IsInteger(value));
+}
+
+// ES6 #sec-number.isnan
+javascript builtin NumberIsNaN(js-implicit context: NativeContext)(
+ value: JSAny): Boolean {
+ typeswitch (value) {
+ case (Smi): {
+ return False;
+ }
+ case (h: HeapNumber): {
+ const number: float64 = Convert<float64>(h);
+ return Convert<Boolean>(Float64IsNaN(number));
+ }
+ case (JSAnyNotNumber): {
+ return False;
+ }
+ }
+}
+
+// ES6 #sec-number.issafeinteger
+javascript builtin NumberIsSafeInteger(js-implicit context: NativeContext)(
+ value: JSAny): Boolean {
+ return SelectBooleanConstant(IsSafeInteger(value));
+}
+
+// ES6 #sec-number.prototype.valueof
+transitioning javascript builtin NumberPrototypeValueOf(
+ js-implicit context: NativeContext, receiver: JSAny)(): JSAny {
+ return ToThisValue(
+ receiver, PrimitiveType::kNumber, 'Number.prototype.valueOf');
+}
+
+// ES6 #sec-number.parsefloat
+transitioning javascript builtin NumberParseFloat(
+ js-implicit context: NativeContext)(value: JSAny): Number {
+ try {
+ typeswitch (value) {
+ case (s: Smi): {
+ return s;
+ }
+ case (h: HeapNumber): {
+ // The input is already a Number. Take care of -0.
+ // The sense of comparison is important for the NaN case.
+ return (Convert<float64>(h) == 0) ? SmiConstant(0) : h;
+ }
+ case (s: String): {
+ goto String(s);
+ }
+ case (HeapObject): {
+ goto String(string::ToString(context, value));
+ }
+ }
+ } label String(s: String) {
+ // Check if the string is a cached array index.
+ const hash: NameHash = s.hash_field;
+ if (!hash.is_not_integer_index_mask &&
+ hash.array_index_length < kMaxCachedArrayIndexLength) {
+ const arrayIndex: uint32 = hash.array_index_value;
+ return SmiFromUint32(arrayIndex);
+ }
+ // Fall back to the runtime to convert string to a number.
+ return runtime::StringParseFloat(s);
+ }
+}
+
+extern macro TruncateFloat64ToWord32(float64): uint32;
+
+transitioning builtin ParseInt(implicit context: Context)(
+ input: JSAny, radix: JSAny): Number {
+ try {
+ // Check if radix should be 10 (i.e. undefined, 0 or 10).
+ if (radix != Undefined && !TaggedEqual(radix, SmiConstant(10)) &&
+ !TaggedEqual(radix, SmiConstant(0))) {
+ goto CallRuntime;
+ }
+
+ typeswitch (input) {
+ case (s: Smi): {
+ return s;
+ }
+ case (h: HeapNumber): {
+ // Check if the input value is in Signed32 range.
+ const asFloat64: float64 = Convert<float64>(h);
+ const asInt32: int32 = Signed(TruncateFloat64ToWord32(asFloat64));
+ // The sense of comparison is important for the NaN case.
+ if (asFloat64 == ChangeInt32ToFloat64(asInt32)) goto Int32(asInt32);
+
+ // Check if the absolute value of input is in the [1,1<<31[ range. Call
+ // the runtime for the range [0,1[ because the result could be -0.
+ const kMaxAbsValue: float64 = 2147483648.0;
+ const absInput: float64 = math::Float64Abs(asFloat64);
+ if (absInput < kMaxAbsValue && absInput >= 1) goto Int32(asInt32);
+ goto CallRuntime;
+ }
+ case (s: String): {
+ goto String(s);
+ }
+ case (HeapObject): {
+ goto CallRuntime;
+ }
+ }
+ } label Int32(i: int32) {
+ return ChangeInt32ToTagged(i);
+ } label String(s: String) {
+ // Check if the string is a cached array index.
+ const hash: NameHash = s.hash_field;
+ if (!hash.is_not_integer_index_mask &&
+ hash.array_index_length < kMaxCachedArrayIndexLength) {
+ const arrayIndex: uint32 = hash.array_index_value;
+ return SmiFromUint32(arrayIndex);
+ }
+ // Fall back to the runtime.
+ goto CallRuntime;
+ } label CallRuntime {
+ tail runtime::StringParseInt(input, radix);
+ }
+}
+
+// ES6 #sec-number.parseint
+transitioning javascript builtin NumberParseInt(
+ js-implicit context: NativeContext)(value: JSAny, radix: JSAny): Number {
+ return ParseInt(value, radix);
+}
+
+extern builtin NonNumberToNumeric(implicit context: Context)(JSAny): Numeric;
+extern builtin BitwiseXor(implicit context: Context)(Number, Number): Number;
+extern builtin Subtract(implicit context: Context)(Number, Number): Number;
+extern builtin Add(implicit context: Context)(Number, Number): Number;
+extern builtin StringAddConvertLeft(implicit context: Context)(
+ JSAny, String): JSAny;
+extern builtin StringAddConvertRight(implicit context: Context)(
+ String, JSAny): JSAny;
+
+extern macro BitwiseOp(int32, int32, constexpr Operation): Number;
+extern macro RelationalComparison(
+ constexpr Operation, JSAny, JSAny, Context): Boolean;
+
+// TODO(bbudge) Use a simpler macro structure that doesn't loop when converting
+// non-numbers, if such a code sequence doesn't make the builtin bigger.
+
+transitioning macro ToNumericOrPrimitive(implicit context: Context)(
+ value: JSAny): JSAny {
+ typeswitch (value) {
+ case (v: JSReceiver): {
+ return NonPrimitiveToPrimitive_Default(context, v);
+ }
+ case (v: JSPrimitive): {
+ return NonNumberToNumeric(v);
+ }
+ }
+}
+
+transitioning builtin Add(implicit context: Context)(
+ leftArg: JSAny, rightArg: JSAny): JSAny {
+ let left: JSAny = leftArg;
+ let right: JSAny = rightArg;
+ try {
+ while (true) {
+ typeswitch (left) {
+ case (left: Smi): {
+ typeswitch (right) {
+ case (right: Smi): {
+ return math::TrySmiAdd(left, right) otherwise goto Float64s(
+ SmiToFloat64(left), SmiToFloat64(right));
+ }
+ case (right: HeapNumber): {
+ goto Float64s(SmiToFloat64(left), Convert<float64>(right));
+ }
+ case (right: BigInt): {
+ goto Numerics(left, right);
+ }
+ case (right: String): {
+ goto StringAddConvertLeft(left, right);
+ }
+ case (HeapObject): {
+ right = ToNumericOrPrimitive(right);
+ continue;
+ }
+ }
+ }
+ case (left: HeapNumber): {
+ typeswitch (right) {
+ case (right: Smi): {
+ goto Float64s(Convert<float64>(left), SmiToFloat64(right));
+ }
+ case (right: HeapNumber): {
+ goto Float64s(Convert<float64>(left), Convert<float64>(right));
+ }
+ case (right: BigInt): {
+ goto Numerics(left, right);
+ }
+ case (right: String): {
+ goto StringAddConvertLeft(left, right);
+ }
+ case (HeapObject): {
+ right = ToNumericOrPrimitive(right);
+ continue;
+ }
+ }
+ }
+ case (left: BigInt): {
+ typeswitch (right) {
+ case (right: Numeric): {
+ goto Numerics(left, right);
+ }
+ case (right: String): {
+ goto StringAddConvertLeft(left, right);
+ }
+ case (HeapObject): {
+ right = ToNumericOrPrimitive(right);
+ continue;
+ }
+ }
+ }
+ case (left: String): {
+ goto StringAddConvertRight(left, right);
+ }
+ case (leftReceiver: JSReceiver): {
+ left = ToPrimitiveDefault(leftReceiver);
+ }
+ case (HeapObject): {
+ // left: HeapObject
+ typeswitch (right) {
+ case (right: String): {
+ goto StringAddConvertLeft(left, right);
+ }
+ case (rightReceiver: JSReceiver): {
+ // left is JSPrimitive and right is JSReceiver, convert right
+ // with priority.
+ right = ToPrimitiveDefault(rightReceiver);
+ continue;
+ }
+ case (JSPrimitive): {
+ // Neither left or right is JSReceiver, convert left.
+ left = NonNumberToNumeric(left);
+ continue;
+ }
+ }
+ }
+ }
+ }
+ } label StringAddConvertLeft(left: JSAny, right: String) {
+ tail StringAddConvertLeft(left, right);
+ } label StringAddConvertRight(left: String, right: JSAny) {
+ tail StringAddConvertRight(left, right);
+ } label Numerics(left: Numeric, right: Numeric) {
+ tail bigint::BigIntAdd(left, right);
+ } label Float64s(left: float64, right: float64) {
+ return AllocateHeapNumberWithValue(left + right);
+ }
+ unreachable;
+}
+
+// Unary type switch on Number | BigInt.
+macro UnaryOp1(implicit context: Context)(value: JSAny): never labels
+Number(Number), BigInt(BigInt) {
+ let x: JSAny = value;
+ while (true) {
+ typeswitch (x) {
+ case (n: Number): {
+ goto Number(n);
+ }
+ case (b: BigInt): {
+ goto BigInt(b);
+ }
+ case (JSAnyNotNumeric): {
+ x = NonNumberToNumeric(x);
+ }
+ }
+ }
+ unreachable;
+}
+
+// Unary type switch on Smi | HeapNumber | BigInt.
+macro UnaryOp2(implicit context: Context)(value: JSAny): never labels
+Smi(Smi), HeapNumber(HeapNumber), BigInt(BigInt) {
+ let x: JSAny = value;
+ while (true) {
+ typeswitch (x) {
+ case (s: Smi): {
+ goto Smi(s);
+ }
+ case (h: HeapNumber): {
+ goto HeapNumber(h);
+ }
+ case (b: BigInt): {
+ goto BigInt(b);
+ }
+ case (JSAnyNotNumeric): {
+ x = NonNumberToNumeric(x);
+ }
+ }
+ }
+ unreachable;
+}
+
+// Binary type switch on Number | BigInt.
+macro BinaryOp1(implicit context: Context)(
+ leftVal: JSAny, rightVal: JSAny): never labels
+Number(Number, Number), AtLeastOneBigInt(Numeric, Numeric) {
+ let left: JSAny = leftVal;
+ let right: JSAny = rightVal;
+ while (true) {
+ try {
+ typeswitch (left) {
+ case (left: Number): {
+ typeswitch (right) {
+ case (right: Number): {
+ goto Number(left, right);
+ }
+ case (right: BigInt): {
+ goto AtLeastOneBigInt(left, right);
+ }
+ case (JSAnyNotNumeric): {
+ goto RightNotNumeric;
+ }
+ }
+ }
+ case (left: BigInt): {
+ typeswitch (right) {
+ case (right: Numeric): {
+ goto AtLeastOneBigInt(left, right);
+ }
+ case (JSAnyNotNumeric): {
+ goto RightNotNumeric;
+ }
+ }
+ }
+ case (JSAnyNotNumeric): {
+ left = NonNumberToNumeric(left);
+ }
+ }
+ } label RightNotNumeric {
+ right = NonNumberToNumeric(right);
+ }
+ }
+ unreachable;
+}
+
+// Binary type switch on Smi | HeapNumber | BigInt.
+macro BinaryOp2(implicit context: Context)(leftVal: JSAny, rightVal: JSAny):
+ never labels Smis(Smi, Smi), Float64s(float64, float64),
+ AtLeastOneBigInt(Numeric, Numeric) {
+ let left: JSAny = leftVal;
+ let right: JSAny = rightVal;
+ while (true) {
+ try {
+ typeswitch (left) {
+ case (left: Smi): {
+ typeswitch (right) {
+ case (right: Smi): {
+ goto Smis(left, right);
+ }
+ case (right: HeapNumber): {
+ goto Float64s(SmiToFloat64(left), Convert<float64>(right));
+ }
+ case (right: BigInt): {
+ goto AtLeastOneBigInt(left, right);
+ }
+ case (JSAnyNotNumeric): {
+ goto RightNotNumeric;
+ }
+ }
+ }
+ case (left: HeapNumber): {
+ typeswitch (right) {
+ case (right: Smi): {
+ goto Float64s(Convert<float64>(left), SmiToFloat64(right));
+ }
+ case (right: HeapNumber): {
+ goto Float64s(Convert<float64>(left), Convert<float64>(right));
+ }
+ case (right: BigInt): {
+ goto AtLeastOneBigInt(left, right);
+ }
+ case (JSAnyNotNumeric): {
+ goto RightNotNumeric;
+ }
+ }
+ }
+ case (left: BigInt): {
+ typeswitch (right) {
+ case (right: Numeric): {
+ goto AtLeastOneBigInt(left, right);
+ }
+ case (JSAnyNotNumeric): {
+ goto RightNotNumeric;
+ }
+ }
+ }
+ case (JSAnyNotNumeric): {
+ left = NonNumberToNumeric(left);
+ }
+ }
+ } label RightNotNumeric {
+ right = NonNumberToNumeric(right);
+ }
+ }
+ unreachable;
+}
+
+builtin Subtract(implicit context: Context)(
+ left: JSAny, right: JSAny): Numeric {
+ try {
+ BinaryOp2(left, right) otherwise Smis, Float64s, AtLeastOneBigInt;
+ } label Smis(left: Smi, right: Smi) {
+ try {
+ return math::TrySmiSub(left, right) otherwise Overflow;
+ } label Overflow {
+ goto Float64s(SmiToFloat64(left), SmiToFloat64(right));
+ }
+ } label Float64s(left: float64, right: float64) {
+ return AllocateHeapNumberWithValue(left - right);
+ } label AtLeastOneBigInt(left: Numeric, right: Numeric) {
+ tail bigint::BigIntSubtract(left, right);
+ }
+}
+
+builtin Multiply(implicit context: Context)(
+ left: JSAny, right: JSAny): Numeric {
+ try {
+ BinaryOp2(left, right) otherwise Smis, Float64s, AtLeastOneBigInt;
+ } label Smis(left: Smi, right: Smi) {
+ // The result is not necessarily a smi, in case of overflow.
+ return SmiMul(left, right);
+ } label Float64s(left: float64, right: float64) {
+ return AllocateHeapNumberWithValue(left * right);
+ } label AtLeastOneBigInt(left: Numeric, right: Numeric) {
+ tail runtime::BigIntBinaryOp(
+ context, left, right, SmiTag<Operation>(Operation::kMultiply));
+ }
+}
+
+const kSmiValueSize: constexpr int32 generates 'kSmiValueSize';
+const kMinInt32: constexpr int32 generates 'kMinInt';
+const kMinInt31: constexpr int32 generates 'kMinInt31';
+const kMinimumDividend: int32 = (kSmiValueSize == 32) ? kMinInt32 : kMinInt31;
+
+builtin Divide(implicit context: Context)(left: JSAny, right: JSAny): Numeric {
+ try {
+ BinaryOp2(left, right) otherwise Smis, Float64s, AtLeastOneBigInt;
+ } label Smis(left: Smi, right: Smi) {
+ // TODO(jkummerow): Consider just always doing a double division.
+ // Bail out if {divisor} is zero.
+ if (right == 0) goto SmiBailout(left, right);
+
+ // Bail out if dividend is zero and divisor is negative.
+ if (left == 0 && right < 0) goto SmiBailout(left, right);
+
+ const dividend: int32 = SmiToInt32(left);
+ const divisor: int32 = SmiToInt32(right);
+
+ // Bail out if dividend is kMinInt31 (or kMinInt32 if Smis are 32 bits)
+ // and divisor is -1.
+ if (divisor == -1 && dividend == kMinimumDividend) {
+ goto SmiBailout(left, right);
+ }
+ // TODO(epertoso): consider adding a machine instruction that returns
+ // both the result and the remainder.
+ const result: int32 = dividend / divisor;
+ const truncated: int32 = result * divisor;
+ if (dividend != truncated) goto SmiBailout(left, right);
+ return SmiFromInt32(result);
+ } label SmiBailout(left: Smi, right: Smi) {
+ goto Float64s(SmiToFloat64(left), SmiToFloat64(right));
+ } label Float64s(left: float64, right: float64) {
+ return AllocateHeapNumberWithValue(left / right);
+ } label AtLeastOneBigInt(left: Numeric, right: Numeric) {
+ tail runtime::BigIntBinaryOp(
+ context, left, right, SmiTag<Operation>(Operation::kDivide));
+ }
+}
+
+builtin Modulus(implicit context: Context)(left: JSAny, right: JSAny): Numeric {
+ try {
+ BinaryOp2(left, right) otherwise Smis, Float64s, AtLeastOneBigInt;
+ } label Smis(left: Smi, right: Smi) {
+ return SmiMod(left, right);
+ } label Float64s(left: float64, right: float64) {
+ return AllocateHeapNumberWithValue(left % right);
+ } label AtLeastOneBigInt(left: Numeric, right: Numeric) {
+ tail runtime::BigIntBinaryOp(
+ context, left, right, SmiTag<Operation>(Operation::kModulus));
+ }
+}
+
+builtin Exponentiate(implicit context: Context)(
+ left: JSAny, right: JSAny): Numeric {
+ try {
+ BinaryOp1(left, right) otherwise Numbers, AtLeastOneBigInt;
+ } label Numbers(left: Number, right: Number) {
+ return math::MathPowImpl(left, right);
+ } label AtLeastOneBigInt(left: Numeric, right: Numeric) {
+ tail runtime::BigIntBinaryOp(
+ context, left, right, SmiTag<Operation>(Operation::kExponentiate));
+ }
+}
+
+builtin Negate(implicit context: Context)(value: JSAny): Numeric {
+ try {
+ UnaryOp2(value) otherwise Smi, HeapNumber, BigInt;
+ } label Smi(s: Smi) {
+ return SmiMul(s, -1);
+ } label HeapNumber(h: HeapNumber) {
+ return AllocateHeapNumberWithValue(Convert<float64>(h) * -1);
+ } label BigInt(b: BigInt) {
+ tail runtime::BigIntUnaryOp(
+ context, b, SmiTag<Operation>(Operation::kNegate));
+ }
+}
+
+builtin BitwiseNot(implicit context: Context)(value: JSAny): Numeric {
+ try {
+ UnaryOp1(value) otherwise Number, BigInt;
+ } label Number(n: Number) {
+ tail BitwiseXor(n, -1);
+ } label BigInt(b: BigInt) {
+ return runtime::BigIntUnaryOp(
+ context, b, SmiTag<Operation>(Operation::kBitwiseNot));
+ }
+}
+
+builtin Decrement(implicit context: Context)(value: JSAny): Numeric {
+ try {
+ UnaryOp1(value) otherwise Number, BigInt;
+ } label Number(n: Number) {
+ tail Subtract(n, 1);
+ } label BigInt(b: BigInt) {
+ return runtime::BigIntUnaryOp(
+ context, b, SmiTag<Operation>(Operation::kDecrement));
+ }
+}
+
+builtin Increment(implicit context: Context)(value: JSAny): Numeric {
+ try {
+ UnaryOp1(value) otherwise Number, BigInt;
+ } label Number(n: Number) {
+ tail Add(n, 1);
+ } label BigInt(b: BigInt) {
+ return runtime::BigIntUnaryOp(
+ context, b, SmiTag<Operation>(Operation::kIncrement));
+ }
+}
+
+// Bitwise binary operations.
+
+extern macro BinaryOpAssembler::Generate_BitwiseBinaryOp(
+ constexpr Operation, JSAny, JSAny, Context): Object;
+
+builtin ShiftLeft(implicit context: Context)(
+ left: JSAny, right: JSAny): Object {
+ return Generate_BitwiseBinaryOp(Operation::kShiftLeft, left, right, context);
+}
+
+builtin ShiftRight(implicit context: Context)(
+ left: JSAny, right: JSAny): Object {
+ return Generate_BitwiseBinaryOp(Operation::kShiftRight, left, right, context);
+}
+
+builtin ShiftRightLogical(implicit context: Context)(
+ left: JSAny, right: JSAny): Object {
+ return Generate_BitwiseBinaryOp(
+ Operation::kShiftRightLogical, left, right, context);
+}
+
+builtin BitwiseAnd(implicit context: Context)(
+ left: JSAny, right: JSAny): Object {
+ return Generate_BitwiseBinaryOp(Operation::kBitwiseAnd, left, right, context);
+}
+
+builtin BitwiseOr(implicit context: Context)(
+ left: JSAny, right: JSAny): Object {
+ return Generate_BitwiseBinaryOp(Operation::kBitwiseOr, left, right, context);
}
+
+builtin BitwiseXor(implicit context: Context)(
+ left: JSAny, right: JSAny): Object {
+ return Generate_BitwiseBinaryOp(Operation::kBitwiseXor, left, right, context);
+}
+
+// Relational builtins.
+
+builtin LessThan(implicit context: Context)(left: JSAny, right: JSAny): Object {
+ return RelationalComparison(Operation::kLessThan, left, right, context);
+}
+
+builtin LessThanOrEqual(implicit context: Context)(
+ left: JSAny, right: JSAny): Object {
+ return RelationalComparison(
+ Operation::kLessThanOrEqual, left, right, context);
+}
+
+builtin GreaterThan(implicit context: Context)(
+ left: JSAny, right: JSAny): Object {
+ return RelationalComparison(Operation::kGreaterThan, left, right, context);
+}
+
+builtin GreaterThanOrEqual(implicit context: Context)(
+ left: JSAny, right: JSAny): Object {
+ return RelationalComparison(
+ Operation::kGreaterThanOrEqual, left, right, context);
+}
+
+builtin Equal(implicit context: Context)(left: JSAny, right: JSAny): Object {
+ return Equal(left, right, context);
+}
+
+builtin StrictEqual(implicit context: Context)(
+ left: JSAny, right: JSAny): Object {
+ return ::StrictEqual(left, right);
+}
+
+} // namespace number
diff --git a/chromium/v8/src/builtins/promise-abstract-operations.tq b/chromium/v8/src/builtins/promise-abstract-operations.tq
index 9cf6da102b8..83dd56aff49 100644
--- a/chromium/v8/src/builtins/promise-abstract-operations.tq
+++ b/chromium/v8/src/builtins/promise-abstract-operations.tq
@@ -24,6 +24,16 @@ PromiseRejectEventFromStack(implicit context: Context)(JSPromise, JSAny): JSAny;
// https://tc39.es/ecma262/#sec-promise-abstract-operations
namespace promise {
+
+extern macro PromiseForwardingHandlerSymbolConstant(): Symbol;
+const kPromiseForwardingHandlerSymbol: Symbol =
+ PromiseForwardingHandlerSymbolConstant();
+extern macro PromiseHandledBySymbolConstant(): Symbol;
+const kPromiseHandledBySymbol: Symbol = PromiseHandledBySymbolConstant();
+extern macro ResolveStringConstant(): String;
+const kResolveString: String = ResolveStringConstant();
+extern macro IsPromiseResolveProtectorCellInvalid(): bool;
+
extern macro AllocateFunctionWithMapAndContext(
Map, SharedFunctionInfo, Context): JSFunction;
@@ -503,6 +513,41 @@ PromiseGetCapabilitiesExecutor(
return Undefined;
}
+macro IsPromiseResolveLookupChainIntact(implicit context: Context)(
+ nativeContext: NativeContext, constructor: JSReceiver): bool {
+ if (IsForceSlowPath()) return false;
+ const promiseFun = UnsafeCast<JSFunction>(
+ nativeContext[NativeContextSlot::PROMISE_FUNCTION_INDEX]);
+ return promiseFun == constructor && !IsPromiseResolveProtectorCellInvalid();
+}
+
+// https://tc39.es/ecma262/#sec-getpromiseresolve
+transitioning macro GetPromiseResolve(implicit context: Context)(
+ nativeContext: NativeContext, constructor: Constructor): JSAny {
+ // 1. Assert: IsConstructor(constructor) is true.
+
+ // We can skip the "resolve" lookup on {constructor} if it's the
+ // Promise constructor and the Promise.resolve protector is intact,
+ // as that guards the lookup path for the "resolve" property on the
+ // Promise constructor. In this case, promiseResolveFunction is undefined,
+ // and when CallResolve is called with it later, it will call Promise.resolve.
+ let promiseResolveFunction: JSAny = Undefined;
+
+ if (!IsPromiseResolveLookupChainIntact(nativeContext, constructor)) {
+ let promiseResolve: JSAny;
+
+ // 2. Let promiseResolve be ? Get(constructor, "resolve").
+ promiseResolve = GetProperty(constructor, kResolveString);
+
+ // 3. If IsCallable(promiseResolve) is false, throw a TypeError exception.
+ promiseResolveFunction =
+ Cast<Callable>(promiseResolve) otherwise ThrowTypeError(
+ MessageTemplate::kCalledNonCallable, 'resolve');
+ }
+ // 4. return promiseResolve.
+ return promiseResolveFunction;
+}
+
transitioning macro CallResolve(implicit context: Context)(
constructor: Constructor, resolve: JSAny, value: JSAny): JSAny {
// Undefined can never be a valid value for the resolve function,
diff --git a/chromium/v8/src/builtins/promise-all-element-closure.tq b/chromium/v8/src/builtins/promise-all-element-closure.tq
index 4dfafec1c92..55f722eb24d 100644
--- a/chromium/v8/src/builtins/promise-all-element-closure.tq
+++ b/chromium/v8/src/builtins/promise-all-element-closure.tq
@@ -66,7 +66,7 @@ extern enum PromiseAllResolveElementContextSlots extends int31
constexpr 'PromiseBuiltins::PromiseAllResolveElementContextSlots' {
kPromiseAllResolveElementRemainingSlot,
kPromiseAllResolveElementCapabilitySlot,
- kPromiseAllResolveElementValuesArraySlot,
+ kPromiseAllResolveElementValuesSlot,
kPromiseAllResolveElementLength
}
extern operator '[]=' macro StoreContextElement(
@@ -106,73 +106,43 @@ transitioning macro PromiseAllResolveElementClosure<F: type>(
assert(identityHash > 0);
const index = identityHash - 1;
- // Check if we need to grow the [[ValuesArray]] to store {value} at {index}.
- const valuesArray = UnsafeCast<JSArray>(
+ let remainingElementsCount =
+ UnsafeCast<Smi>(context[PromiseAllResolveElementContextSlots::
+ kPromiseAllResolveElementRemainingSlot]);
+
+ let values =
+ UnsafeCast<FixedArray>(context[PromiseAllResolveElementContextSlots::
+ kPromiseAllResolveElementValuesSlot]);
+ const newCapacity = index + 1;
+ if (newCapacity > values.length_intptr) deferred {
+ // This happens only when the promises are resolved during iteration.
+ values = ExtractFixedArray(values, 0, values.length_intptr, newCapacity);
context[PromiseAllResolveElementContextSlots::
- kPromiseAllResolveElementValuesArraySlot]);
- const elements = UnsafeCast<FixedArray>(valuesArray.elements);
- const valuesLength = Convert<intptr>(valuesArray.length);
- if (index < valuesLength) {
- // The {index} is in bounds of the {values_array}, check if this element has
- // already been resolved, and store the {value} if not.
- //
- // Promise.allSettled, for each input element, has both a resolve and a
- // reject closure that share an [[AlreadyCalled]] boolean. That is, the
- // input element can only be settled once: after resolve is called, reject
- // returns early, and vice versa. Using {function}'s context as the marker
- // only tracks per-closure instead of per-element. When the second
- // resolve/reject closure is called on the same index, values.object[index]
- // will already exist and will not be the hole value. In that case, return
- // early. Everything up to this point is not yet observable to user code.
- // This is not a problem for Promise.all since Promise.all has a single
- // resolve closure (no reject) per element.
- if (hasResolveAndRejectClosures) {
- if (elements.objects[index] != TheHole) deferred {
- return Undefined;
- }
+ kPromiseAllResolveElementValuesSlot] = values;
}
- // Update the value depending on whether Promise.all or
- // Promise.allSettled is called.
- const updatedValue = wrapResultFunctor.Call(nativeContext, value);
- elements.objects[index] = updatedValue;
- } else {
- // Check if we need to grow the backing store.
- //
- // There's no need to check if this element has already been resolved for
- // Promise.allSettled if {values_array} has not yet grown to the index.
- const newLength = index + 1;
- const elementsLength = elements.length_intptr;
-
- // Update the value depending on whether Promise.all or
- // Promise.allSettled is called.
- const updatedValue = wrapResultFunctor.Call(nativeContext, value);
-
- if (index < elementsLength) {
- // The {index} is within bounds of the {elements} backing store, so
- // just store the {value} and update the "length" of the {values_array}.
- valuesArray.length = Convert<Smi>(newLength);
- elements.objects[index] = updatedValue;
- } else
- deferred {
- // We need to grow the backing store to fit the {index} as well.
- const newElementsLength = IntPtrMin(
- CalculateNewElementsCapacity(newLength),
- kPropertyArrayHashFieldMax + 1);
- assert(index < newElementsLength);
- assert(elementsLength < newElementsLength);
- const newElements =
- ExtractFixedArray(elements, 0, elementsLength, newElementsLength);
- newElements.objects[index] = updatedValue;
-
- // Update backing store and "length" on {values_array}.
- valuesArray.elements = newElements;
- valuesArray.length = Convert<Smi>(newLength);
+ // Promise.allSettled, for each input element, has both a resolve and a reject
+ // closure that share an [[AlreadyCalled]] boolean. That is, the input element
+ // can only be settled once: after resolve is called, reject returns early,
+ // and vice versa. Using {function}'s context as the marker only tracks
+ // per-closure instead of per-element. When the second resolve/reject closure
+ // is called on the same index, values.object[index] will already exist and
+ // will not be the hole value. In that case, return early. Everything up to
+ // this point is not yet observable to user code. This is not a problem for
+ // Promise.all since Promise.all has a single resolve closure (no reject) per
+ // element.
+ if (hasResolveAndRejectClosures) {
+ if (values.objects[index] != TheHole) deferred {
+ return Undefined;
}
}
- let remainingElementsCount =
- UnsafeCast<Smi>(context[PromiseAllResolveElementContextSlots::
- kPromiseAllResolveElementRemainingSlot]);
+
+ // Update the value depending on whether Promise.all or
+ // Promise.allSettled is called.
+ const updatedValue = wrapResultFunctor.Call(nativeContext, value);
+
+ values.objects[index] = updatedValue;
+
remainingElementsCount = remainingElementsCount - 1;
context[PromiseAllResolveElementContextSlots::
kPromiseAllResolveElementRemainingSlot] = remainingElementsCount;
@@ -181,6 +151,9 @@ transitioning macro PromiseAllResolveElementClosure<F: type>(
context[PromiseAllResolveElementContextSlots::
kPromiseAllResolveElementCapabilitySlot]);
const resolve = UnsafeCast<JSAny>(capability.resolve);
+ const arrayMap = UnsafeCast<Map>(
+ nativeContext[NativeContextSlot::JS_ARRAY_PACKED_ELEMENTS_MAP_INDEX]);
+ const valuesArray = NewJSArray(arrayMap, values);
Call(context, resolve, Undefined, valuesArray);
}
return Undefined;
diff --git a/chromium/v8/src/builtins/promise-all.tq b/chromium/v8/src/builtins/promise-all.tq
index b7fad88f6fc..302d4f3251c 100644
--- a/chromium/v8/src/builtins/promise-all.tq
+++ b/chromium/v8/src/builtins/promise-all.tq
@@ -18,12 +18,6 @@ const kPromiseBuiltinsPromiseContextLength: constexpr int31
// case to mark it's done).
macro CreatePromiseAllResolveElementContext(implicit context: Context)(
capability: PromiseCapability, nativeContext: NativeContext): Context {
- // TODO(bmeurer): Manually fold this into a single allocation.
- const arrayMap = UnsafeCast<Map>(
- nativeContext[NativeContextSlot::JS_ARRAY_PACKED_ELEMENTS_MAP_INDEX]);
- const valuesArray = AllocateJSArray(
- ElementsKind::PACKED_ELEMENTS, arrayMap, IntPtrConstant(0),
- SmiConstant(0));
const resolveContext = AllocateSyntheticFunctionContext(
nativeContext,
PromiseAllResolveElementContextSlots::kPromiseAllResolveElementLength);
@@ -32,7 +26,7 @@ macro CreatePromiseAllResolveElementContext(implicit context: Context)(
resolveContext[PromiseAllResolveElementContextSlots::
kPromiseAllResolveElementCapabilitySlot] = capability;
resolveContext[PromiseAllResolveElementContextSlots::
- kPromiseAllResolveElementValuesArraySlot] = valuesArray;
+ kPromiseAllResolveElementValuesSlot] = kEmptyFixedArray;
return resolveContext;
}
@@ -115,11 +109,11 @@ struct PromiseAllSettledRejectElementFunctor {
transitioning macro PerformPromiseAll<F1: type, F2: type>(
implicit context: Context)(
- constructor: JSReceiver, capability: PromiseCapability,
- iter: iterator::IteratorRecord, createResolveElementFunctor: F1,
+ nativeContext: NativeContext, iter: iterator::IteratorRecord,
+ constructor: Constructor, capability: PromiseCapability,
+ promiseResolveFunction: JSAny, createResolveElementFunctor: F1,
createRejectElementFunctor: F2): JSAny labels
Reject(Object) {
- const nativeContext = LoadNativeContext(context);
const promise = capability.promise;
const resolve = capability.resolve;
const reject = capability.reject;
@@ -135,141 +129,119 @@ Reject(Object) {
let index: Smi = 1;
- // We can skip the "resolve" lookup on {constructor} if it's the
- // Promise constructor and the Promise.resolve protector is intact,
- // as that guards the lookup path for the "resolve" property on the
- // Promise constructor.
- let promiseResolveFunction: JSAny = Undefined;
try {
- try {
- if (!IsPromiseResolveLookupChainIntact(nativeContext, constructor)) {
- let promiseResolve: JSAny;
-
- // 5. Let _promiseResolve_ be ? Get(_constructor_, `"resolve"`).
- promiseResolve = GetProperty(constructor, kResolveString);
-
- // 6. If IsCallable(_promiseResolve_) is *false*, throw a *TypeError*
- // exception.
- promiseResolveFunction =
- Cast<Callable>(promiseResolve) otherwise ThrowTypeError(
- MessageTemplate::kCalledNonCallable, 'resolve');
+ const fastIteratorResultMap = UnsafeCast<Map>(
+ nativeContext[NativeContextSlot::ITERATOR_RESULT_MAP_INDEX]);
+ while (true) {
+ let nextValue: JSAny;
+ try {
+ // Let next be IteratorStep(iteratorRecord.[[Iterator]]).
+ // If next is an abrupt completion, set iteratorRecord.[[Done]] to
+ // true. ReturnIfAbrupt(next).
+ const next: JSReceiver = iterator::IteratorStep(
+ iter, fastIteratorResultMap) otherwise goto Done;
+
+ // Let nextValue be IteratorValue(next).
+ // If nextValue is an abrupt completion, set iteratorRecord.[[Done]]
+ // to true.
+ // ReturnIfAbrupt(nextValue).
+ nextValue = iterator::IteratorValue(next, fastIteratorResultMap);
+ } catch (e) {
+ goto Reject(e);
}
- const fastIteratorResultMap = UnsafeCast<Map>(
- nativeContext[NativeContextSlot::ITERATOR_RESULT_MAP_INDEX]);
- while (true) {
- let nextValue: JSAny;
- try {
- // Let next be IteratorStep(iteratorRecord.[[Iterator]]).
- // If next is an abrupt completion, set iteratorRecord.[[Done]] to
- // true. ReturnIfAbrupt(next).
- const next: JSReceiver = iterator::IteratorStep(
- iter, fastIteratorResultMap) otherwise goto Done;
-
- // Let nextValue be IteratorValue(next).
- // If nextValue is an abrupt completion, set iteratorRecord.[[Done]]
- // to true.
- // ReturnIfAbrupt(nextValue).
- nextValue = iterator::IteratorValue(next, fastIteratorResultMap);
- } catch (e) {
- goto Reject(e);
- }
-
- // Check if we reached the limit.
- if (index == kPropertyArrayHashFieldMax) {
- // If there are too many elements (currently more than 2**21-1),
- // raise a RangeError here (which is caught below and turned into
- // a rejection of the resulting promise). We could gracefully handle
- // this case as well and support more than this number of elements
- // by going to a separate function and pass the larger indices via a
- // separate context, but it doesn't seem likely that we need this,
- // and it's unclear how the rest of the system deals with 2**21 live
- // Promises anyway.
- ThrowRangeError(
- MessageTemplate::kTooManyElementsInPromiseCombinator, 'all');
- }
-
- // Set remainingElementsCount.[[Value]] to
- // remainingElementsCount.[[Value]] + 1.
- const remainingElementsCount = UnsafeCast<Smi>(
- resolveElementContext[PromiseAllResolveElementContextSlots::
- kPromiseAllResolveElementRemainingSlot]);
- resolveElementContext[PromiseAllResolveElementContextSlots::
- kPromiseAllResolveElementRemainingSlot] =
- remainingElementsCount + 1;
-
- // Let resolveElement be CreateBuiltinFunction(steps,
- // « [[AlreadyCalled]],
- // [[Index]],
- // [[Values]],
- // [[Capability]],
- // [[RemainingElements]]
- // »).
- // Set resolveElement.[[AlreadyCalled]] to a Record { [[Value]]: false
- // }. Set resolveElement.[[Index]] to index. Set
- // resolveElement.[[Values]] to values. Set
- // resolveElement.[[Capability]] to resultCapability. Set
- // resolveElement.[[RemainingElements]] to remainingElementsCount.
- const resolveElementFun = createResolveElementFunctor.Call(
- resolveElementContext, nativeContext, index, capability);
- const rejectElementFun = createRejectElementFunctor.Call(
- resolveElementContext, nativeContext, index, capability);
-
- // We can skip the "resolve" lookup on the {constructor} as well as
- // the "then" lookup on the result of the "resolve" call, and
- // immediately chain continuation onto the {next_value} if:
- //
- // (a) The {constructor} is the intrinsic %Promise% function, and
- // looking up "resolve" on {constructor} yields the initial
- // Promise.resolve() builtin, and
- // (b) the promise @@species protector cell is valid, meaning that
- // no one messed with the Symbol.species property on any
- // intrinsic promise or on the Promise.prototype, and
- // (c) the {next_value} is a JSPromise whose [[Prototype]] field
- // contains the intrinsic %PromisePrototype%, and
- // (d) we're not running with async_hooks or DevTools enabled.
- //
- // In that case we also don't need to allocate a chained promise for
- // the PromiseReaction (aka we can pass undefined to
- // PerformPromiseThen), since this is only necessary for DevTools and
- // PromiseHooks.
- if (promiseResolveFunction != Undefined ||
- IsPromiseHookEnabledOrDebugIsActiveOrHasAsyncEventDelegate() ||
- IsPromiseSpeciesProtectorCellInvalid() || Is<Smi>(nextValue) ||
- !IsPromiseThenLookupChainIntact(
- nativeContext, UnsafeCast<HeapObject>(nextValue).map)) {
- // Let nextPromise be ? Call(constructor, _promiseResolve_, «
- // nextValue »).
- const nextPromise = CallResolve(
- UnsafeCast<Constructor>(constructor), promiseResolveFunction,
- nextValue);
-
- // Perform ? Invoke(nextPromise, "then", « resolveElement,
- // resultCapability.[[Reject]] »).
- const then = GetProperty(nextPromise, kThenString);
- const thenResult = Call(
- nativeContext, then, nextPromise, resolveElementFun,
- rejectElementFun);
-
- // For catch prediction, mark that rejections here are
- // semantically handled by the combined Promise.
- if (IsDebugActive() && Is<JSPromise>(thenResult)) deferred {
- SetPropertyStrict(
- context, thenResult, kPromiseHandledBySymbol, promise);
- }
- } else {
- PerformPromiseThenImpl(
- UnsafeCast<JSPromise>(nextValue), resolveElementFun,
- rejectElementFun, Undefined);
- }
-
- // Set index to index + 1.
- index += 1;
+ // Check if we reached the limit.
+ if (index == kPropertyArrayHashFieldMax) {
+ // If there are too many elements (currently more than 2**21-1),
+ // raise a RangeError here (which is caught below and turned into
+ // a rejection of the resulting promise). We could gracefully handle
+ // this case as well and support more than this number of elements
+ // by going to a separate function and pass the larger indices via a
+ // separate context, but it doesn't seem likely that we need this,
+ // and it's unclear how the rest of the system deals with 2**21 live
+ // Promises anyway.
+ ThrowRangeError(
+ MessageTemplate::kTooManyElementsInPromiseCombinator, 'all');
}
- } catch (e) deferred {
- iterator::IteratorCloseOnException(iter);
- goto Reject(e);
+
+ // Set remainingElementsCount.[[Value]] to
+ // remainingElementsCount.[[Value]] + 1.
+ const remainingElementsCount = UnsafeCast<Smi>(
+ resolveElementContext[PromiseAllResolveElementContextSlots::
+ kPromiseAllResolveElementRemainingSlot]);
+ resolveElementContext[PromiseAllResolveElementContextSlots::
+ kPromiseAllResolveElementRemainingSlot] =
+ remainingElementsCount + 1;
+
+ // Let resolveElement be CreateBuiltinFunction(steps,
+ // « [[AlreadyCalled]],
+ // [[Index]],
+ // [[Values]],
+ // [[Capability]],
+ // [[RemainingElements]]
+ // »).
+ // Set resolveElement.[[AlreadyCalled]] to a Record { [[Value]]: false
+ // }. Set resolveElement.[[Index]] to index. Set
+ // resolveElement.[[Values]] to values. Set
+ // resolveElement.[[Capability]] to resultCapability. Set
+ // resolveElement.[[RemainingElements]] to remainingElementsCount.
+ const resolveElementFun = createResolveElementFunctor.Call(
+ resolveElementContext, nativeContext, index, capability);
+ const rejectElementFun = createRejectElementFunctor.Call(
+ resolveElementContext, nativeContext, index, capability);
+
+ // We can skip the "then" lookup on the result of the "resolve" call and
+ // immediately chain the continuation onto the {next_value} if:
+ //
+ // (a) The {constructor} is the intrinsic %Promise% function, and
+ // looking up "resolve" on {constructor} yields the initial
+ // Promise.resolve() builtin, and
+ // (b) the promise @@species protector cell is valid, meaning that
+ // no one messed with the Symbol.species property on any
+ // intrinsic promise or on the Promise.prototype, and
+ // (c) the {next_value} is a JSPromise whose [[Prototype]] field
+ // contains the intrinsic %PromisePrototype%, and
+ // (d) we're not running with async_hooks or DevTools enabled.
+ //
+ // In that case we also don't need to allocate a chained promise for
+ // the PromiseReaction (aka we can pass undefined to
+ // PerformPromiseThen), since this is only necessary for DevTools and
+ // PromiseHooks.
+ if (promiseResolveFunction != Undefined ||
+ IsPromiseHookEnabledOrDebugIsActiveOrHasAsyncEventDelegate() ||
+ IsPromiseSpeciesProtectorCellInvalid() || Is<Smi>(nextValue) ||
+ !IsPromiseThenLookupChainIntact(
+ nativeContext, UnsafeCast<HeapObject>(nextValue).map)) {
+ // Let nextPromise be ? Call(constructor, _promiseResolve_, «
+ // nextValue »).
+ const nextPromise =
+ CallResolve(constructor, promiseResolveFunction, nextValue);
+
+ // Perform ? Invoke(nextPromise, "then", « resolveElement,
+ // resultCapability.[[Reject]] »).
+ const then = GetProperty(nextPromise, kThenString);
+ const thenResult = Call(
+ nativeContext, then, nextPromise, resolveElementFun,
+ rejectElementFun);
+
+ // For catch prediction, mark that rejections here are
+ // semantically handled by the combined Promise.
+ if (IsDebugActive() && Is<JSPromise>(thenResult)) deferred {
+ SetPropertyStrict(
+ context, thenResult, kPromiseHandledBySymbol, promise);
+ }
+ } else {
+ PerformPromiseThenImpl(
+ UnsafeCast<JSPromise>(nextValue), resolveElementFun,
+ rejectElementFun, Undefined);
+ }
+
+ // Set index to index + 1.
+ index += 1;
}
+ } catch (e) deferred {
+ iterator::IteratorCloseOnException(iter);
+ goto Reject(e);
} label Done {}
// Set iteratorRecord.[[Done]] to true.
@@ -283,30 +255,36 @@ Reject(Object) {
kPromiseAllResolveElementRemainingSlot] =
remainingElementsCount;
if (remainingElementsCount > 0) {
- // Pre-allocate the backing store for the {values_array} to the desired
- // capacity here. We may already have elements here in case of some
- // fancy Thenable that calls the resolve callback immediately, so we need
- // to handle that correctly here.
- const valuesArray = UnsafeCast<JSArray>(
+ // Pre-allocate the backing store for the {values} to the desired
+ // capacity. We may already have elements in "values" - this happens
+ // when the Thenable calls the resolve callback immediately.
+ let values = UnsafeCast<FixedArray>(
resolveElementContext[PromiseAllResolveElementContextSlots::
- kPromiseAllResolveElementValuesArraySlot]);
- const oldElements = UnsafeCast<FixedArray>(valuesArray.elements);
- const oldCapacity = oldElements.length_intptr;
- const newCapacity = SmiUntag(index);
+ kPromiseAllResolveElementValuesSlot]);
+ // 'index' is a 1-based index and incremented after every Promise. Later we
+ // use 'values' as a 0-based array, so capacity 'index - 1' is enough.
+ const newCapacity = SmiUntag(index) - 1;
+
+ const oldCapacity = values.length_intptr;
if (oldCapacity < newCapacity) {
- valuesArray.elements =
- ExtractFixedArray(oldElements, 0, oldCapacity, newCapacity);
+ values = ExtractFixedArray(values, 0, oldCapacity, newCapacity);
+ resolveElementContext[PromiseAllResolveElementContextSlots::
+ kPromiseAllResolveElementValuesSlot] = values;
}
} else
deferred {
+ assert(remainingElementsCount == 0);
// If remainingElementsCount.[[Value]] is 0, then
// Let valuesArray be CreateArrayFromList(values).
// Perform ? Call(resultCapability.[[Resolve]], undefined,
// « valuesArray »).
- assert(remainingElementsCount == 0);
- const valuesArray = UnsafeCast<JSAny>(
+
+ const values = UnsafeCast<FixedArray>(
resolveElementContext[PromiseAllResolveElementContextSlots::
- kPromiseAllResolveElementValuesArraySlot]);
+ kPromiseAllResolveElementValuesSlot]);
+ const arrayMap = UnsafeCast<Map>(
+ nativeContext[NativeContextSlot::JS_ARRAY_PACKED_ELEMENTS_MAP_INDEX]);
+ const valuesArray = NewJSArray(arrayMap, values);
Call(nativeContext, UnsafeCast<JSAny>(resolve), Undefined, valuesArray);
}
@@ -318,6 +296,7 @@ transitioning macro GeneratePromiseAll<F1: type, F2: type>(
implicit context: Context)(
receiver: JSAny, iterable: JSAny, createResolveElementFunctor: F1,
createRejectElementFunctor: F2): JSAny {
+ const nativeContext = LoadNativeContext(context);
// Let C be the this value.
// If Type(C) is not Object, throw a TypeError exception.
const receiver = Cast<JSReceiver>(receiver)
@@ -328,7 +307,16 @@ transitioning macro GeneratePromiseAll<F1: type, F2: type>(
// not trigger redundant ExceptionEvents
const capability = NewPromiseCapability(receiver, False);
+ // NewPromiseCapability guarantees that receiver is Constructor.
+ assert(Is<Constructor>(receiver));
+ const constructor = UnsafeCast<Constructor>(receiver);
+
try {
+ // Let promiseResolve be GetPromiseResolve(C).
+ // IfAbruptRejectPromise(promiseResolve, promiseCapability).
+ const promiseResolveFunction =
+ GetPromiseResolve(nativeContext, constructor);
+
// Let iterator be GetIterator(iterable).
// IfAbruptRejectPromise(iterator, promiseCapability).
let i = iterator::GetIterator(iterable);
@@ -339,8 +327,9 @@ transitioning macro GeneratePromiseAll<F1: type, F2: type>(
// IteratorClose(iterator, result).
// IfAbruptRejectPromise(result, promiseCapability).
return PerformPromiseAll(
- receiver, capability, i, createResolveElementFunctor,
- createRejectElementFunctor) otherwise Reject;
+ nativeContext, i, constructor, capability, promiseResolveFunction,
+ createResolveElementFunctor, createRejectElementFunctor)
+ otherwise Reject;
} catch (e) deferred {
goto Reject(e);
} label Reject(e: Object) deferred {
diff --git a/chromium/v8/src/builtins/promise-any.tq b/chromium/v8/src/builtins/promise-any.tq
index 1046ed0a89c..2fefdf4baad 100644
--- a/chromium/v8/src/builtins/promise-any.tq
+++ b/chromium/v8/src/builtins/promise-any.tq
@@ -9,7 +9,7 @@ extern enum PromiseAnyRejectElementContextSlots extends int31
constexpr 'PromiseBuiltins::PromiseAnyRejectElementContextSlots' {
kPromiseAnyRejectElementRemainingSlot,
kPromiseAnyRejectElementCapabilitySlot,
- kPromiseAnyRejectElementErrorsArraySlot,
+ kPromiseAnyRejectElementErrorsSlot,
kPromiseAnyRejectElementLength
}
@@ -35,9 +35,8 @@ transitioning macro CreatePromiseAnyRejectElementContext(
kPromiseAnyRejectElementRemainingSlot] = SmiConstant(1);
rejectContext[PromiseAnyRejectElementContextSlots::
kPromiseAnyRejectElementCapabilitySlot] = capability;
- // Will be set later.
rejectContext[PromiseAnyRejectElementContextSlots::
- kPromiseAnyRejectElementErrorsArraySlot] = Undefined;
+ kPromiseAnyRejectElementErrorsSlot] = kEmptyFixedArray;
return rejectContext;
}
@@ -92,17 +91,9 @@ PromiseAnyRejectElementClosure(
const index = identityHash - 1;
// 6. Let errors be F.[[Errors]].
- if (context[PromiseAnyRejectElementContextSlots::
- kPromiseAnyRejectElementErrorsArraySlot] == Undefined) {
- // We're going to reject the Promise with a more fundamental error (e.g.,
- // something went wrong with iterating the Promises). We don't need to
- // construct the "errors" array.
- return Undefined;
- }
-
- const errorsArray = UnsafeCast<FixedArray>(
- context[PromiseAnyRejectElementContextSlots::
- kPromiseAnyRejectElementErrorsArraySlot]);
+ let errors =
+ UnsafeCast<FixedArray>(context[PromiseAnyRejectElementContextSlots::
+ kPromiseAnyRejectElementErrorsSlot]);
// 7. Let promiseCapability be F.[[Capability]].
@@ -110,8 +101,15 @@ PromiseAnyRejectElementClosure(
let remainingElementsCount =
UnsafeCast<Smi>(context[PromiseAnyRejectElementContextSlots::
kPromiseAnyRejectElementRemainingSlot]);
+
// 9. Set errors[index] to x.
- errorsArray.objects[index] = value;
+ const newCapacity = IntPtrMax(SmiUntag(remainingElementsCount), index + 1);
+ if (newCapacity > errors.length_intptr) deferred {
+ errors = ExtractFixedArray(errors, 0, errors.length_intptr, newCapacity);
+ context[PromiseAnyRejectElementContextSlots::
+ kPromiseAnyRejectElementErrorsSlot] = errors;
+ }
+ errors.objects[index] = value;
// 10. Set remainingElementsCount.[[Value]] to
// remainingElementsCount.[[Value]] - 1.
@@ -124,7 +122,7 @@ PromiseAnyRejectElementClosure(
// a. Let error be a newly created AggregateError object.
// b. Set error.[[AggregateErrors]] to errors.
- const error = ConstructAggregateError(errorsArray);
+ const error = ConstructAggregateError(errors);
// c. Return ? Call(promiseCapability.[[Reject]], undefined, « error »).
const capability = UnsafeCast<PromiseCapability>(
context[PromiseAnyRejectElementContextSlots::
@@ -137,16 +135,15 @@ PromiseAnyRejectElementClosure(
}
transitioning macro PerformPromiseAny(implicit context: Context)(
- iteratorRecord: iterator::IteratorRecord, constructor: Constructor,
- resultCapability: PromiseCapability): JSAny labels
+ nativeContext: NativeContext, iteratorRecord: iterator::IteratorRecord,
+ constructor: Constructor, resultCapability: PromiseCapability,
+ promiseResolveFunction: JSAny): JSAny labels
Reject(Object) {
// 1. Assert: ! IsConstructor(constructor) is true.
// 2. Assert: resultCapability is a PromiseCapability Record.
- const nativeContext = LoadNativeContext(context);
-
- // 3. Let errors be a new empty List.
- let growableErrorsArray = growable_fixed_array::NewGrowableFixedArray();
+ // 3. Let errors be a new empty List. (Do nothing: errors is
+ // initialized lazily when the first Promise rejects.)
// 4. Let remainingElementsCount be a new Record { [[Value]]: 1 }.
const rejectElementContext =
@@ -157,21 +154,6 @@ Reject(Object) {
let index: Smi = 1;
try {
- // We can skip the "resolve" lookup on {constructor} if it's the
- // Promise constructor and the Promise.resolve protector is intact,
- // as that guards the lookup path for the "resolve" property on the
- // Promise constructor.
- let promiseResolveFunction: JSAny = Undefined;
- if (!IsPromiseResolveLookupChainIntact(nativeContext, constructor))
- deferred {
- // 6. Let promiseResolve be ? Get(constructor, `"resolve"`).
- const promiseResolve = GetProperty(constructor, kResolveString);
- // 7. If IsCallable(promiseResolve) is false, throw a
- // TypeError exception.
- promiseResolveFunction = Cast<Callable>(promiseResolve)
- otherwise ThrowTypeError(
- MessageTemplate::kCalledNonCallable, 'resolve');
- }
const fastIteratorResultMap = UnsafeCast<Map>(
nativeContext[NativeContextSlot::ITERATOR_RESULT_MAP_INDEX]);
// 8. Repeat,
@@ -215,8 +197,8 @@ Reject(Object) {
MessageTemplate::kTooManyElementsInPromiseCombinator, 'any');
}
- // h. Append undefined to errors.
- growableErrorsArray.Push(Undefined);
+ // h. Append undefined to errors. (Do nothing: errors is initialized
+ // lazily when the first Promise rejects.)
let nextPromise: JSAny;
// i. Let nextPromise be ? Call(constructor, promiseResolve,
@@ -291,16 +273,18 @@ Reject(Object) {
kPromiseAnyRejectElementRemainingSlot] =
remainingElementsCount;
- const errorsArray = growableErrorsArray.ToFixedArray();
- rejectElementContext[PromiseAnyRejectElementContextSlots::
- kPromiseAnyRejectElementErrorsArraySlot] =
- errorsArray;
-
// iii. If remainingElementsCount.[[Value]] is 0, then
if (remainingElementsCount == 0) deferred {
// 1. Let error be a newly created AggregateError object.
// 2. Set error.[[AggregateErrors]] to errors.
- const error = ConstructAggregateError(errorsArray);
+
+ // We may already have elements in "errors" - this happens when the
+ // Thenable calls the reject callback immediately.
+ const errors = UnsafeCast<FixedArray>(
+ rejectElementContext[PromiseAnyRejectElementContextSlots::
+ kPromiseAnyRejectElementErrorsSlot]);
+
+ const error = ConstructAggregateError(errors);
// 3. Return ThrowCompletion(error).
goto Reject(error);
}
@@ -312,6 +296,8 @@ Reject(Object) {
transitioning javascript builtin
PromiseAny(
js-implicit context: Context, receiver: JSAny)(iterable: JSAny): JSAny {
+ const nativeContext = LoadNativeContext(context);
+
// 1. Let C be the this value.
const receiver = Cast<JSReceiver>(receiver)
otherwise ThrowTypeError(MessageTemplate::kCalledOnNonObject, 'Promise.any');
@@ -319,37 +305,42 @@ PromiseAny(
// 2. Let promiseCapability be ? NewPromiseCapability(C).
const capability = NewPromiseCapability(receiver, False);
- // NewPromiseCapability guarantees that receiver is Constructor
+ // NewPromiseCapability guarantees that receiver is Constructor.
assert(Is<Constructor>(receiver));
const constructor = UnsafeCast<Constructor>(receiver);
try {
- let iteratorRecord: iterator::IteratorRecord;
- try {
- // 3. Let iteratorRecord be GetIterator(iterable).
+ // 3. Let promiseResolve be GetPromiseResolve(C).
+ // 4. IfAbruptRejectPromise(promiseResolve, promiseCapability).
+ // (catch below)
+ const promiseResolveFunction =
+ GetPromiseResolve(nativeContext, constructor);
- // 4. IfAbruptRejectPromise(iteratorRecord, promiseCapability).
- // (catch below)
- iteratorRecord = iterator::GetIterator(iterable);
+ // 5. Let iteratorRecord be GetIterator(iterable).
- // 5. Let result be PerformPromiseAny(iteratorRecord, C,
- // promiseCapability).
+ // 6. IfAbruptRejectPromise(iteratorRecord, promiseCapability).
+ // (catch below)
+ const iteratorRecord = iterator::GetIterator(iterable);
- // 6. If result is an abrupt completion, then
+ // 7. Let result be PerformPromiseAny(iteratorRecord, C,
+ // promiseCapability).
- // a. If iteratorRecord.[[Done]] is false, set result to
- // IteratorClose(iteratorRecord, result).
+ // 8. If result is an abrupt completion, then
- // b. IfAbruptRejectPromise(result, promiseCapability).
+ // a. If iteratorRecord.[[Done]] is false, set result to
+ // IteratorClose(iteratorRecord, result).
- // [Iterator closing handled by PerformPromiseAny]
+ // b. IfAbruptRejectPromise(result, promiseCapability).
- // 7. Return Completion(result).
- return PerformPromiseAny(iteratorRecord, constructor, capability)
- otherwise Reject;
- } catch (e) deferred {
- goto Reject(e);
- }
+ // [Iterator closing handled by PerformPromiseAny]
+
+ // 9. Return Completion(result).
+ return PerformPromiseAny(
+ nativeContext, iteratorRecord, constructor, capability,
+ promiseResolveFunction)
+ otherwise Reject;
+ } catch (e) deferred {
+ goto Reject(e);
} label Reject(e: Object) deferred {
// Exception must be bound to a JS value.
assert(e != TheHole);
@@ -361,10 +352,13 @@ PromiseAny(
}
transitioning macro ConstructAggregateError(implicit context: Context)(
- errorsArray: FixedArray): JSObject {
- const obj: JSAggregateError = error::ConstructInternalAggregateErrorHelper(
+ errors: FixedArray): JSObject {
+ const obj: JSObject = error::ConstructInternalAggregateErrorHelper(
context, SmiConstant(MessageTemplate::kAllPromisesRejected));
- obj.errors = errorsArray;
+ const errorsJSArray = array::CreateJSArrayWithElements(errors);
+ SetOwnPropertyIgnoreAttributes(
+ obj, ErrorsStringConstant(), errorsJSArray,
+ SmiConstant(PropertyAttributes::DONT_ENUM));
return obj;
}
diff --git a/chromium/v8/src/builtins/promise-race.tq b/chromium/v8/src/builtins/promise-race.tq
index 27d2038398a..26ffb7ae554 100644
--- a/chromium/v8/src/builtins/promise-race.tq
+++ b/chromium/v8/src/builtins/promise-race.tq
@@ -6,24 +6,6 @@
namespace promise {
-extern macro PromiseForwardingHandlerSymbolConstant(): Symbol;
-const kPromiseForwardingHandlerSymbol: Symbol =
- PromiseForwardingHandlerSymbolConstant();
-extern macro PromiseHandledBySymbolConstant(): Symbol;
-const kPromiseHandledBySymbol: Symbol = PromiseHandledBySymbolConstant();
-extern macro ResolveStringConstant(): String;
-const kResolveString: String = ResolveStringConstant();
-extern macro SetPropertyStrict(Context, Object, Object, Object): Object;
-extern macro IsPromiseResolveProtectorCellInvalid(): bool;
-
-macro IsPromiseResolveLookupChainIntact(implicit context: Context)(
- nativeContext: NativeContext, constructor: JSReceiver): bool {
- if (IsForceSlowPath()) return false;
- const promiseFun = UnsafeCast<JSFunction>(
- nativeContext[NativeContextSlot::PROMISE_FUNCTION_INDEX]);
- return promiseFun == constructor && !IsPromiseResolveProtectorCellInvalid();
-}
-
// https://tc39.es/ecma262/#sec-promise.race
transitioning javascript builtin
PromiseRace(
@@ -31,6 +13,8 @@ PromiseRace(
const receiver = Cast<JSReceiver>(receiver)
otherwise ThrowTypeError(MessageTemplate::kCalledOnNonObject, 'Promise.race');
+ const nativeContext = LoadNativeContext(context);
+
// Let promiseCapability be ? NewPromiseCapability(C).
// Don't fire debugEvent so that forwarding the rejection through all does
// not trigger redundant ExceptionEvents
@@ -39,6 +23,10 @@ PromiseRace(
const reject = capability.reject;
const promise = capability.promise;
+ // NewPromiseCapability guarantees that receiver is Constructor.
+ assert(Is<Constructor>(receiver));
+ const constructor = UnsafeCast<Constructor>(receiver);
+
// For catch prediction, don't treat the .then calls as handling it;
// instead, recurse outwards.
if (IsDebugActive()) deferred {
@@ -46,10 +34,15 @@ PromiseRace(
}
try {
- // Let iterator be GetIterator(iterable).
- // IfAbruptRejectPromise(iterator, promiseCapability).
+ let promiseResolveFunction: JSAny;
let i: iterator::IteratorRecord;
try {
+ // Let promiseResolve be GetPromiseResolve(C).
+ // IfAbruptRejectPromise(promiseResolve, promiseCapability).
+ promiseResolveFunction = GetPromiseResolve(nativeContext, constructor);
+
+ // Let iterator be GetIterator(iterable).
+ // IfAbruptRejectPromise(iterator, promiseCapability).
i = iterator::GetIterator(iterable);
} catch (e) deferred {
goto Reject(e);
@@ -57,24 +50,6 @@ PromiseRace(
// Let result be PerformPromiseRace(iteratorRecord, C, promiseCapability).
try {
- // We can skip the "resolve" lookup on {constructor} if it's the
- // Promise constructor and the Promise.resolve protector is intact,
- // as that guards the lookup path for the "resolve" property on the
- // Promise constructor.
- const nativeContext = LoadNativeContext(context);
- let promiseResolveFunction: JSAny = Undefined;
- if (!IsPromiseResolveLookupChainIntact(nativeContext, receiver))
- deferred {
- // 3. Let _promiseResolve_ be ? Get(_constructor_, `"resolve"`).
- const resolve = GetProperty(receiver, kResolveString);
-
- // 4. If IsCallable(_promiseResolve_) is *false*, throw a
- // *TypeError* exception.
- promiseResolveFunction = Cast<Callable>(resolve)
- otherwise ThrowTypeError(
- MessageTemplate::kCalledNonCallable, 'resolve');
- }
-
const fastIteratorResultMap = UnsafeCast<Map>(
nativeContext[NativeContextSlot::ITERATOR_RESULT_MAP_INDEX]);
while (true) {
@@ -96,9 +71,8 @@ PromiseRace(
}
// Let nextPromise be ? Call(constructor, _promiseResolve_, «
// nextValue »).
- const nextPromise = CallResolve(
- UnsafeCast<Constructor>(receiver), promiseResolveFunction,
- nextValue);
+ const nextPromise =
+ CallResolve(constructor, promiseResolveFunction, nextValue);
// Perform ? Invoke(nextPromise, "then", « resolveElement,
// resultCapability.[[Reject]] »).
diff --git a/chromium/v8/src/builtins/regexp.tq b/chromium/v8/src/builtins/regexp.tq
index 21577b47634..603b456661d 100644
--- a/chromium/v8/src/builtins/regexp.tq
+++ b/chromium/v8/src/builtins/regexp.tq
@@ -186,8 +186,7 @@ extern enum Flag constexpr 'JSRegExp::Flag' {
kMultiline,
kSticky,
kUnicode,
- kDotAll,
- kInvalid
+ kDotAll
}
const kRegExpPrototypeOldFlagGetter: constexpr int31
diff --git a/chromium/v8/src/builtins/setup-builtins-internal.cc b/chromium/v8/src/builtins/setup-builtins-internal.cc
index 4739e18c57f..d094c3f2ad4 100644
--- a/chromium/v8/src/builtins/setup-builtins-internal.cc
+++ b/chromium/v8/src/builtins/setup-builtins-internal.cc
@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "src/init/setup-isolate.h"
-
#include "src/builtins/builtins.h"
#include "src/codegen/assembler-inl.h"
#include "src/codegen/interface-descriptors.h"
@@ -12,7 +10,8 @@
#include "src/compiler/code-assembler.h"
#include "src/execution/isolate.h"
#include "src/handles/handles-inl.h"
-#include "src/heap/heap-inl.h" // For MemoryAllocator::code_range.
+#include "src/heap/heap-inl.h" // For Heap::code_range.
+#include "src/init/setup-isolate.h"
#include "src/interpreter/bytecodes.h"
#include "src/interpreter/interpreter-generator.h"
#include "src/interpreter/interpreter.h"
diff --git a/chromium/v8/src/builtins/torque-internal.tq b/chromium/v8/src/builtins/torque-internal.tq
index d2b107f932d..5a75f5ca726 100644
--- a/chromium/v8/src/builtins/torque-internal.tq
+++ b/chromium/v8/src/builtins/torque-internal.tq
@@ -186,6 +186,28 @@ macro StoreFloat64OrHole(r:&float64_or_hole, value: float64_or_hole) {
* unsafe::NewReference<float64>(r.object, r.offset) = value.value;
}
}
+
+macro DownCastForTorqueClass<T : type extends HeapObject>(o: HeapObject):
+ T labels CastError {
+ const map = o.map;
+ const minInstanceType = %MinInstanceType<T>();
+ const maxInstanceType = %MaxInstanceType<T>();
+ if constexpr (minInstanceType == maxInstanceType) {
+ if constexpr (%ClassHasMapConstant<T>()) {
+ if (map != %GetClassMapConstant<T>()) goto CastError;
+ } else {
+ if (map.instance_type != minInstanceType) goto CastError;
+ }
+ } else {
+ const diff: int32 = maxInstanceType - minInstanceType;
+ const offset = Convert<int32>(Convert<uint16>(map.instance_type)) -
+ Convert<int32>(Convert<uint16>(
+ FromConstexpr<InstanceType>(minInstanceType)));
+ if (Unsigned(offset) > Unsigned(diff)) goto CastError;
+ }
+ return %RawDownCast<T>(o);
+}
+
} // namespace torque_internal
// Indicates that an array-field should not be initialized.
@@ -198,6 +220,12 @@ struct UninitializedIterator {}
intrinsic %RawDownCast<To: type, From: type>(x: From): To;
intrinsic %RawConstexprCast<To: type, From: type>(f: From): To;
+intrinsic %MinInstanceType<T: type>(): constexpr InstanceType;
+intrinsic %MaxInstanceType<T: type>(): constexpr InstanceType;
+
+intrinsic %ClassHasMapConstant<T: type>(): constexpr bool;
+intrinsic %GetClassMapConstant<T: type>(): Map;
+
struct IteratorSequence<T: type, FirstIterator: type, SecondIterator: type> {
macro Empty(): bool {
return this.first.Empty() && this.second.Empty();
diff --git a/chromium/v8/src/builtins/typed-array-entries.tq b/chromium/v8/src/builtins/typed-array-entries.tq
new file mode 100644
index 00000000000..6749a14e90a
--- /dev/null
+++ b/chromium/v8/src/builtins/typed-array-entries.tq
@@ -0,0 +1,27 @@
+// Copyright 2019 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include 'src/builtins/builtins-typed-array-gen.h'
+
+namespace typed_array {
+const kBuiltinNameEntries: constexpr string = '%TypedArray%.prototype.entries';
+
+// %TypedArray%.entries ()
+// https://tc39.github.io/ecma262/#sec-%typedarray%.entries
+transitioning javascript builtin
+TypedArrayPrototypeEntries(js-implicit context: NativeContext, receiver: JSAny)(
+ ...arguments): JSArrayIterator {
+ try {
+ const array: JSTypedArray = Cast<JSTypedArray>(receiver)
+ otherwise NotTypedArray;
+
+ EnsureAttached(array) otherwise IsDetached;
+ return CreateArrayIterator(array, IterationKind::kEntries);
+ } label NotTypedArray deferred {
+ ThrowTypeError(MessageTemplate::kNotTypedArray, kBuiltinNameEntries);
+ } label IsDetached deferred {
+ ThrowTypeError(MessageTemplate::kDetachedOperation, kBuiltinNameEntries);
+ }
+}
+}
diff --git a/chromium/v8/src/builtins/typed-array-keys.tq b/chromium/v8/src/builtins/typed-array-keys.tq
new file mode 100644
index 00000000000..24c53c71052
--- /dev/null
+++ b/chromium/v8/src/builtins/typed-array-keys.tq
@@ -0,0 +1,27 @@
+// Copyright 2019 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include 'src/builtins/builtins-typed-array-gen.h'
+
+namespace typed_array {
+const kBuiltinNameKeys: constexpr string = '%TypedArray%.prototype.keys';
+
+// %TypedArray%.keys ()
+// https://tc39.github.io/ecma262/#sec-%typedarray%.keys
+transitioning javascript builtin
+TypedArrayPrototypeKeys(js-implicit context: NativeContext, receiver: JSAny)(
+ ...arguments): JSArrayIterator {
+ try {
+ const array: JSTypedArray = Cast<JSTypedArray>(receiver)
+ otherwise NotTypedArray;
+
+ EnsureAttached(array) otherwise IsDetached;
+ return CreateArrayIterator(array, IterationKind::kKeys);
+ } label NotTypedArray deferred {
+ ThrowTypeError(MessageTemplate::kNotTypedArray, kBuiltinNameKeys);
+ } label IsDetached deferred {
+ ThrowTypeError(MessageTemplate::kDetachedOperation, kBuiltinNameKeys);
+ }
+}
+}
diff --git a/chromium/v8/src/builtins/typed-array-values.tq b/chromium/v8/src/builtins/typed-array-values.tq
new file mode 100644
index 00000000000..a60aaaf707f
--- /dev/null
+++ b/chromium/v8/src/builtins/typed-array-values.tq
@@ -0,0 +1,27 @@
+// Copyright 2019 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include 'src/builtins/builtins-typed-array-gen.h'
+
+namespace typed_array {
+const kBuiltinNameValues: constexpr string = '%TypedArray%.prototype.values';
+
+// %TypedArray%.values ()
+// https://tc39.github.io/ecma262/#sec-%typedarray%.values
+transitioning javascript builtin
+TypedArrayPrototypeValues(js-implicit context: NativeContext, receiver: JSAny)(
+ ...arguments): JSArrayIterator {
+ try {
+ const array: JSTypedArray = Cast<JSTypedArray>(receiver)
+ otherwise NotTypedArray;
+
+ EnsureAttached(array) otherwise IsDetached;
+ return CreateArrayIterator(array, IterationKind::kValues);
+ } label NotTypedArray deferred {
+ ThrowTypeError(MessageTemplate::kNotTypedArray, kBuiltinNameValues);
+ } label IsDetached deferred {
+ ThrowTypeError(MessageTemplate::kDetachedOperation, kBuiltinNameValues);
+ }
+}
+}
diff --git a/chromium/v8/src/builtins/wasm.tq b/chromium/v8/src/builtins/wasm.tq
index 097e39d430e..690df7afecc 100644
--- a/chromium/v8/src/builtins/wasm.tq
+++ b/chromium/v8/src/builtins/wasm.tq
@@ -7,6 +7,10 @@
namespace runtime {
extern runtime WasmMemoryGrow(Context, WasmInstanceObject, Smi): Smi;
extern runtime WasmRefFunc(Context, WasmInstanceObject, Smi): JSAny;
+extern runtime WasmTableInit(
+ Context, WasmInstanceObject, Object, Object, Smi, Smi, Smi): JSAny;
+extern runtime WasmTableCopy(
+ Context, WasmInstanceObject, Object, Object, Smi, Smi, Smi): JSAny;
extern runtime WasmFunctionTableGet(
Context, WasmInstanceObject, Smi, Smi): JSAny;
extern runtime WasmFunctionTableSet(
@@ -17,11 +21,24 @@ extern runtime ReThrow(Context, Object): JSAny;
extern runtime WasmStackGuard(Context): JSAny;
extern runtime ThrowWasmStackOverflow(Context): JSAny;
extern runtime WasmTraceMemory(Context, Smi): JSAny;
+extern runtime WasmTraceEnter(Context): JSAny;
+extern runtime WasmTraceExit(Context, Smi): JSAny;
+extern runtime WasmAtomicNotify(
+ Context, WasmInstanceObject, Number, Number): Smi;
+extern runtime WasmI32AtomicWait(
+ Context, WasmInstanceObject, Number, Number, BigInt): Smi;
+extern runtime WasmI64AtomicWait(
+ Context, WasmInstanceObject, Number, BigInt, BigInt): Smi;
+}
+
+namespace unsafe {
+extern macro TimesTaggedSize(intptr): intptr;
+extern macro Allocate(intptr): HeapObject;
}
namespace wasm {
const kFuncTableType:
- constexpr int31 generates 'wasm::ValueType::Kind::kFuncRef';
+ constexpr int31 generates 'wasm::HeapType::kHeapFunc';
extern macro WasmBuiltinsAssembler::LoadInstanceFromFrame(): WasmInstanceObject;
@@ -33,6 +50,8 @@ extern macro WasmBuiltinsAssembler::LoadTablesFromInstance(WasmInstanceObject):
FixedArray;
extern macro WasmBuiltinsAssembler::LoadExternalFunctionsFromInstance(
WasmInstanceObject): FixedArray;
+extern macro WasmBuiltinsAssembler::LoadManagedObjectMapsFromInstance(
+ WasmInstanceObject): FixedArray;
macro LoadContextFromFrame(): NativeContext {
return LoadContextFromInstance(LoadInstanceFromFrame());
@@ -61,6 +80,38 @@ builtin WasmMemoryGrow(numPages: int32): int32 {
return SmiToInt32(result);
}
+builtin WasmTableInit(
+ dstRaw: uint32, srcRaw: uint32, sizeRaw: uint32, tableIndex: Smi,
+ segmentIndex: Smi): JSAny {
+ try {
+ const instance: WasmInstanceObject = LoadInstanceFromFrame();
+ const dst: Smi = Convert<PositiveSmi>(dstRaw) otherwise TableOutOfBounds;
+ const src: Smi = Convert<PositiveSmi>(srcRaw) otherwise TableOutOfBounds;
+ const size: Smi = Convert<PositiveSmi>(sizeRaw) otherwise TableOutOfBounds;
+ tail runtime::WasmTableInit(
+ LoadContextFromInstance(instance), instance, tableIndex, segmentIndex,
+ dst, src, size);
+ } label TableOutOfBounds deferred {
+ tail ThrowWasmTrapTableOutOfBounds();
+ }
+}
+
+builtin WasmTableCopy(
+ dstRaw: uint32, srcRaw: uint32, sizeRaw: uint32, dstTable: Smi,
+ srcTable: Smi): JSAny {
+ try {
+ const instance: WasmInstanceObject = LoadInstanceFromFrame();
+ const dst: Smi = Convert<PositiveSmi>(dstRaw) otherwise TableOutOfBounds;
+ const src: Smi = Convert<PositiveSmi>(srcRaw) otherwise TableOutOfBounds;
+ const size: Smi = Convert<PositiveSmi>(sizeRaw) otherwise TableOutOfBounds;
+ tail runtime::WasmTableCopy(
+ LoadContextFromInstance(instance), instance, dstTable, srcTable, dst,
+ src, size);
+ } label TableOutOfBounds deferred {
+ tail ThrowWasmTrapTableOutOfBounds();
+ }
+}
+
builtin WasmTableGet(tableIndex: intptr, index: int32): Object {
const instance: WasmInstanceObject = LoadInstanceFromFrame();
const entryIndex: intptr = ChangeInt32ToIntPtr(index);
@@ -145,7 +196,7 @@ builtin WasmThrow(exception: Object): JSAny {
}
builtin WasmRethrow(exception: Object): JSAny {
- if (exception == Null) tail ThrowWasmTrapRethrowNullRef();
+ if (exception == Null) tail ThrowWasmTrapRethrowNull();
tail runtime::ReThrow(LoadContextFromFrame(), exception);
}
@@ -161,11 +212,77 @@ builtin WasmTraceMemory(info: Smi): JSAny {
tail runtime::WasmTraceMemory(LoadContextFromFrame(), info);
}
+builtin WasmTraceEnter(): JSAny {
+ tail runtime::WasmTraceEnter(LoadContextFromFrame());
+}
+
+builtin WasmTraceExit(info: Smi): JSAny {
+ tail runtime::WasmTraceExit(LoadContextFromFrame(), info);
+}
+
builtin WasmAllocateJSArray(implicit context: Context)(size: Smi): JSArray {
const map: Map = GetFastPackedElementsJSArrayMap();
return AllocateJSArray(ElementsKind::PACKED_ELEMENTS, map, size, size);
}
+builtin WasmAllocateStruct(implicit context: Context)(mapIndex: Smi):
+ HeapObject {
+ const instance: WasmInstanceObject = LoadInstanceFromFrame();
+ const maps: FixedArray = LoadManagedObjectMapsFromInstance(instance);
+ const map: Map = %RawDownCast<Map>(LoadFixedArrayElement(maps, mapIndex));
+ const instanceSize: intptr =
+ unsafe::TimesTaggedSize(Convert<intptr>(map.instance_size_in_words));
+ const result: HeapObject = unsafe::Allocate(instanceSize);
+ * UnsafeConstCast(& result.map) = map;
+ return result;
+}
+
+builtin WasmInt32ToNumber(value: int32): Number {
+ return ChangeInt32ToTagged(value);
+}
+
+builtin WasmUint32ToNumber(value: uint32): Number {
+ return ChangeUint32ToTagged(value);
+}
+
+extern builtin I64ToBigInt(intptr): BigInt;
+
+builtin WasmAtomicNotify(address: uint32, count: uint32): uint32 {
+ const instance: WasmInstanceObject = LoadInstanceFromFrame();
+ const result: Smi = runtime::WasmAtomicNotify(
+ LoadContextFromInstance(instance), instance, WasmUint32ToNumber(address),
+ WasmUint32ToNumber(count));
+ return Unsigned(SmiToInt32(result));
+}
+
+builtin WasmI32AtomicWait64(
+ address: uint32, expectedValue: int32, timeout: intptr): uint32 {
+ if constexpr (Is64()) {
+ const instance: WasmInstanceObject = LoadInstanceFromFrame();
+ const result: Smi = runtime::WasmI32AtomicWait(
+ LoadContextFromInstance(instance), instance,
+ WasmUint32ToNumber(address), WasmInt32ToNumber(expectedValue),
+ I64ToBigInt(timeout));
+ return Unsigned(SmiToInt32(result));
+ } else {
+ unreachable;
+ }
+}
+
+builtin WasmI64AtomicWait64(
+ address: uint32, expectedValue: intptr, timeout: intptr): uint32 {
+ if constexpr (Is64()) {
+ const instance: WasmInstanceObject = LoadInstanceFromFrame();
+ const result: Smi = runtime::WasmI64AtomicWait(
+ LoadContextFromInstance(instance), instance,
+ WasmUint32ToNumber(address), I64ToBigInt(expectedValue),
+ I64ToBigInt(timeout));
+ return Unsigned(SmiToInt32(result));
+ } else {
+ unreachable;
+ }
+}
+
extern macro TryHasOwnProperty(HeapObject, Map, InstanceType, Name): never
labels Found, NotFound, Bailout;
type OnNonExistent constexpr 'OnNonExistent';
@@ -251,12 +368,12 @@ builtin ThrowWasmTrapTableOutOfBounds(): JSAny {
tail WasmTrap(SmiConstant(MessageTemplate::kWasmTrapTableOutOfBounds));
}
-builtin ThrowWasmTrapBrOnExnNullRef(): JSAny {
- tail WasmTrap(SmiConstant(MessageTemplate::kWasmTrapBrOnExnNullRef));
+builtin ThrowWasmTrapBrOnExnNull(): JSAny {
+ tail WasmTrap(SmiConstant(MessageTemplate::kWasmTrapBrOnExnNull));
}
-builtin ThrowWasmTrapRethrowNullRef(): JSAny {
- tail WasmTrap(SmiConstant(MessageTemplate::kWasmTrapRethrowNullRef));
+builtin ThrowWasmTrapRethrowNull(): JSAny {
+ tail WasmTrap(SmiConstant(MessageTemplate::kWasmTrapRethrowNull));
}
builtin ThrowWasmTrapNullDereference(): JSAny {