diff options
author | Refael Ackermann <refack@gmail.com> | 2019-05-28 08:46:21 -0400 |
---|---|---|
committer | Refael Ackermann <refack@gmail.com> | 2019-06-01 09:55:12 -0400 |
commit | ed74896b1fae1c163b3906163f3bf46326618ddb (patch) | |
tree | 7fb05c5a19808e0c5cd95837528e9005999cf540 /deps/v8/src/builtins | |
parent | 2a850cd0664a4eee51f44d0bb8c2f7a3fe444154 (diff) | |
download | android-node-v8-ed74896b1fae1c163b3906163f3bf46326618ddb.tar.gz android-node-v8-ed74896b1fae1c163b3906163f3bf46326618ddb.tar.bz2 android-node-v8-ed74896b1fae1c163b3906163f3bf46326618ddb.zip |
deps: update V8 to 7.5.288.22
PR-URL: https://github.com/nodejs/node/pull/27375
Reviewed-By: Michaël Zasso <targos@protonmail.com>
Reviewed-By: Ujjwal Sharma <usharma1998@gmail.com>
Reviewed-By: Refael Ackermann <refack@gmail.com>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: Rich Trott <rtrott@gmail.com>
Diffstat (limited to 'deps/v8/src/builtins')
73 files changed, 2492 insertions, 1615 deletions
diff --git a/deps/v8/src/builtins/arguments.tq b/deps/v8/src/builtins/arguments.tq index 3a6c26c000..4ae22a66ac 100644 --- a/deps/v8/src/builtins/arguments.tq +++ b/deps/v8/src/builtins/arguments.tq @@ -2,6 +2,16 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +struct Arguments { + const frame: FrameWithArguments; + const base: RawPtr; + const length: intptr; +} + +extern operator '[]' macro GetArgumentValue(Arguments, intptr): Object; + +extern macro GetFrameArguments(FrameWithArguments, intptr): Arguments; + namespace arguments { struct ArgumentsInfo { @@ -33,12 +43,16 @@ namespace arguments { const adaptor: ArgumentsAdaptorFrame = Cast<ArgumentsAdaptorFrame>(frame.caller) - otherwise return ArgumentsInfo{frame, argumentCount, formalParameterCount}; + otherwise return ArgumentsInfo{ + frame, + argument_count: argumentCount, + formal_parameter_count: formalParameterCount + }; return ArgumentsInfo{ - adaptor, - Convert<bint>(adaptor.length), - formalParameterCount + frame: adaptor, + argument_count: Convert<bint>(adaptor.length), + formal_parameter_count: formalParameterCount }; } } diff --git a/deps/v8/src/builtins/arm/builtins-arm.cc b/deps/v8/src/builtins/arm/builtins-arm.cc index 6c5a59ff8c..e0a5a90978 100644 --- a/deps/v8/src/builtins/arm/builtins-arm.cc +++ b/deps/v8/src/builtins/arm/builtins-arm.cc @@ -73,15 +73,11 @@ void Builtins::Generate_InternalArrayConstructor(MacroAssembler* masm) { static void GenerateTailCallToReturnedCode(MacroAssembler* masm, Runtime::FunctionId function_id) { // ----------- S t a t e ------------- - // -- r0 : argument count (preserved for callee) // -- r1 : target function (preserved for callee) // -- r3 : new target (preserved for callee) // ----------------------------------- { FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL); - // Push the number of arguments to the callee. - __ SmiTag(r0); - __ push(r0); // Push a copy of the target function and the new target. __ push(r1); __ push(r3); @@ -94,8 +90,6 @@ static void GenerateTailCallToReturnedCode(MacroAssembler* masm, // Restore target function and new target. __ pop(r3); __ pop(r1); - __ pop(r0); - __ SmiUntag(r0, r0); } static_assert(kJavaScriptCallCodeStartRegister == r2, "ABI mismatch"); __ JumpCodeObject(r2); @@ -103,6 +97,20 @@ static void GenerateTailCallToReturnedCode(MacroAssembler* masm, namespace { +void Generate_StackOverflowCheck(MacroAssembler* masm, Register num_args, + Register scratch, Label* stack_overflow) { + // Check the stack for overflow. We are not trying to catch + // interruptions (e.g. debug break and preemption) here, so the "real stack + // limit" is checked. + __ LoadRoot(scratch, RootIndex::kRealStackLimit); + // Make scratch the space we have left. The stack might already be overflowed + // here which will cause scratch to become negative. + __ sub(scratch, sp, scratch); + // Check if the arguments will overflow the stack. + __ cmp(scratch, Operand(num_args, LSL, kPointerSizeLog2)); + __ b(le, stack_overflow); // Signed comparison. +} + void Generate_JSBuiltinsConstructStubHelper(MacroAssembler* masm) { // ----------- S t a t e ------------- // -- r0 : number of arguments @@ -115,6 +123,10 @@ void Generate_JSBuiltinsConstructStubHelper(MacroAssembler* masm) { Register scratch = r2; + Label stack_overflow; + + Generate_StackOverflowCheck(masm, r0, scratch, &stack_overflow); + // Enter a construct frame. { FrameAndConstantPoolScope scope(masm, StackFrame::CONSTRUCT); @@ -170,20 +182,13 @@ void Generate_JSBuiltinsConstructStubHelper(MacroAssembler* masm) { __ add(sp, sp, Operand(scratch, LSL, kPointerSizeLog2 - kSmiTagSize)); __ add(sp, sp, Operand(kPointerSize)); __ Jump(lr); -} -void Generate_StackOverflowCheck(MacroAssembler* masm, Register num_args, - Register scratch, Label* stack_overflow) { - // Check the stack for overflow. We are not trying to catch - // interruptions (e.g. debug break and preemption) here, so the "real stack - // limit" is checked. - __ LoadRoot(scratch, RootIndex::kRealStackLimit); - // Make scratch the space we have left. The stack might already be overflowed - // here which will cause scratch to become negative. - __ sub(scratch, sp, scratch); - // Check if the arguments will overflow the stack. - __ cmp(scratch, Operand(num_args, LSL, kPointerSizeLog2)); - __ b(le, stack_overflow); // Signed comparison. + __ bind(&stack_overflow); + { + FrameScope scope(masm, StackFrame::INTERNAL); + __ CallRuntime(Runtime::kThrowStackOverflow); + __ bkpt(0); // Unreachable code. + } } } // namespace @@ -880,13 +885,11 @@ static void MaybeTailCallOptimizedCodeSlot(MacroAssembler* masm, Register scratch1, Register scratch2, Register scratch3) { // ----------- S t a t e ------------- - // -- r0 : argument count (preserved for callee if needed, and caller) // -- r3 : new target (preserved for callee if needed, and caller) // -- r1 : target function (preserved for callee if needed, and caller) // -- feedback vector (preserved for caller if needed) // ----------------------------------- - DCHECK( - !AreAliased(feedback_vector, r0, r1, r3, scratch1, scratch2, scratch3)); + DCHECK(!AreAliased(feedback_vector, r1, r3, scratch1, scratch2, scratch3)); Label optimized_code_slot_is_weak_ref, fallthrough; @@ -1071,8 +1074,10 @@ void Builtins::Generate_InterpreterEntryTrampoline(MacroAssembler* masm) { Label push_stack_frame; // Check if feedback vector is valid. If valid, check for optimized code // and update invocation count. Otherwise, setup the stack frame. - __ CompareRoot(feedback_vector, RootIndex::kUndefinedValue); - __ b(eq, &push_stack_frame); + __ ldr(r4, FieldMemOperand(feedback_vector, HeapObject::kMapOffset)); + __ ldrh(r4, FieldMemOperand(r4, Map::kInstanceTypeOffset)); + __ cmp(r4, Operand(FEEDBACK_VECTOR_TYPE)); + __ b(ne, &push_stack_frame); // Read off the optimized code slot in the feedback vector, and if there // is optimized code or an optimization marker, call that instead. @@ -1092,10 +1097,15 @@ void Builtins::Generate_InterpreterEntryTrampoline(MacroAssembler* masm) { FrameScope frame_scope(masm, StackFrame::MANUAL); __ PushStandardFrame(closure); - // Reset code age. - __ mov(r9, Operand(BytecodeArray::kNoAgeBytecodeAge)); - __ strb(r9, FieldMemOperand(kInterpreterBytecodeArrayRegister, - BytecodeArray::kBytecodeAgeOffset)); + // Reset code age and the OSR arming. The OSR field and BytecodeAgeOffset are + // 8-bit fields next to each other, so we could just optimize by writing a + // 16-bit. These static asserts guard our assumption is valid. + STATIC_ASSERT(BytecodeArray::kBytecodeAgeOffset == + BytecodeArray::kOSRNestingLevelOffset + kCharSize); + STATIC_ASSERT(BytecodeArray::kNoAgeBytecodeAge == 0); + __ mov(r9, Operand(0)); + __ strh(r9, FieldMemOperand(kInterpreterBytecodeArrayRegister, + BytecodeArray::kOSRNestingLevelOffset)); // Load the initial bytecode offset. __ mov(kInterpreterBytecodeOffsetRegister, diff --git a/deps/v8/src/builtins/arm64/builtins-arm64.cc b/deps/v8/src/builtins/arm64/builtins-arm64.cc index 0a5e691cf3..36fa042324 100644 --- a/deps/v8/src/builtins/arm64/builtins-arm64.cc +++ b/deps/v8/src/builtins/arm64/builtins-arm64.cc @@ -69,7 +69,6 @@ void Builtins::Generate_InternalArrayConstructor(MacroAssembler* masm) { static void GenerateTailCallToReturnedCode(MacroAssembler* masm, Runtime::FunctionId function_id) { // ----------- S t a t e ------------- - // -- x0 : argument count (preserved for callee) // -- x1 : target function (preserved for callee) // -- x3 : new target (preserved for callee) // ----------------------------------- @@ -77,16 +76,14 @@ static void GenerateTailCallToReturnedCode(MacroAssembler* masm, FrameScope scope(masm, StackFrame::INTERNAL); // Push a copy of the target function and the new target. // Push another copy as a parameter to the runtime call. - __ SmiTag(x0); - __ Push(x0, x1, x3, padreg); + __ Push(x1, x3); __ PushArgument(x1); __ CallRuntime(function_id, 1); __ Mov(x2, x0); // Restore target function and new target. - __ Pop(padreg, x3, x1, x0); - __ SmiUntag(x0); + __ Pop(x3, x1); } static_assert(kJavaScriptCallCodeStartRegister == x2, "ABI mismatch"); @@ -95,6 +92,44 @@ static void GenerateTailCallToReturnedCode(MacroAssembler* masm, namespace { +void Generate_StackOverflowCheck(MacroAssembler* masm, Register num_args, + Label* stack_overflow) { + UseScratchRegisterScope temps(masm); + Register scratch = temps.AcquireX(); + + // Check the stack for overflow. + // We are not trying to catch interruptions (e.g. debug break and + // preemption) here, so the "real stack limit" is checked. + + __ LoadRoot(scratch, RootIndex::kRealStackLimit); + // Make scratch the space we have left. The stack might already be overflowed + // here which will cause scratch to become negative. + __ Sub(scratch, sp, scratch); + // Check if the arguments will overflow the stack. + __ Cmp(scratch, Operand(num_args, LSL, kSystemPointerSizeLog2)); + __ B(le, stack_overflow); + +#if defined(V8_OS_WIN) + // Simulate _chkstk to extend stack guard page on Windows ARM64. + const int kPageSize = 4096; + Label chkstk, chkstk_done; + Register probe = temps.AcquireX(); + + __ Sub(scratch, sp, Operand(num_args, LSL, kSystemPointerSizeLog2)); + __ Mov(probe, sp); + + // Loop start of stack probe. + __ Bind(&chkstk); + __ Sub(probe, probe, kPageSize); + __ Cmp(probe, scratch); + __ B(lo, &chkstk_done); + __ Ldrb(xzr, MemOperand(probe)); + __ B(&chkstk); + + __ Bind(&chkstk_done); +#endif +} + void Generate_JSBuiltinsConstructStubHelper(MacroAssembler* masm) { // ----------- S t a t e ------------- // -- x0 : number of arguments @@ -106,6 +141,9 @@ void Generate_JSBuiltinsConstructStubHelper(MacroAssembler* masm) { // ----------------------------------- ASM_LOCATION("Builtins::Generate_JSConstructStubHelper"); + Label stack_overflow; + + Generate_StackOverflowCheck(masm, x0, &stack_overflow); // Enter a construct frame. { @@ -196,44 +234,13 @@ void Generate_JSBuiltinsConstructStubHelper(MacroAssembler* masm) { // Remove caller arguments from the stack and return. __ DropArguments(x1, TurboAssembler::kCountExcludesReceiver); __ Ret(); -} -void Generate_StackOverflowCheck(MacroAssembler* masm, Register num_args, - Label* stack_overflow) { - UseScratchRegisterScope temps(masm); - Register scratch = temps.AcquireX(); - - // Check the stack for overflow. - // We are not trying to catch interruptions (e.g. debug break and - // preemption) here, so the "real stack limit" is checked. - - __ LoadRoot(scratch, RootIndex::kRealStackLimit); - // Make scratch the space we have left. The stack might already be overflowed - // here which will cause scratch to become negative. - __ Sub(scratch, sp, scratch); - // Check if the arguments will overflow the stack. - __ Cmp(scratch, Operand(num_args, LSL, kSystemPointerSizeLog2)); - __ B(le, stack_overflow); - -#if defined(V8_OS_WIN) - // Simulate _chkstk to extend stack guard page on Windows ARM64. - const int kPageSize = 4096; - Label chkstk, chkstk_done; - Register probe = temps.AcquireX(); - - __ Sub(scratch, sp, Operand(num_args, LSL, kSystemPointerSizeLog2)); - __ Mov(probe, sp); - - // Loop start of stack probe. - __ Bind(&chkstk); - __ Sub(probe, probe, kPageSize); - __ Cmp(probe, scratch); - __ B(lo, &chkstk_done); - __ Ldrb(xzr, MemOperand(probe)); - __ B(&chkstk); - - __ Bind(&chkstk_done); -#endif + __ Bind(&stack_overflow); + { + FrameScope scope(masm, StackFrame::INTERNAL); + __ CallRuntime(Runtime::kThrowStackOverflow); + __ Unreachable(); + } } } // namespace @@ -999,13 +1006,11 @@ static void MaybeTailCallOptimizedCodeSlot(MacroAssembler* masm, Register scratch1, Register scratch2, Register scratch3) { // ----------- S t a t e ------------- - // -- x0 : argument count (preserved for callee if needed, and caller) // -- x3 : new target (preserved for callee if needed, and caller) // -- x1 : target function (preserved for callee if needed, and caller) // -- feedback vector (preserved for caller if needed) // ----------------------------------- - DCHECK( - !AreAliased(feedback_vector, x0, x1, x3, scratch1, scratch2, scratch3)); + DCHECK(!AreAliased(feedback_vector, x1, x3, scratch1, scratch2, scratch3)); Label optimized_code_slot_is_weak_ref, fallthrough; @@ -1069,10 +1074,10 @@ static void MaybeTailCallOptimizedCodeSlot(MacroAssembler* masm, scratch2, FieldMemOperand(optimized_code_entry, Code::kCodeDataContainerOffset)); __ Ldr( - scratch2, + scratch2.W(), FieldMemOperand(scratch2, CodeDataContainer::kKindSpecificFlagsOffset)); - __ TestAndBranchIfAnySet(scratch2, 1 << Code::kMarkedForDeoptimizationBit, - &found_deoptimized_code); + __ Tbnz(scratch2.W(), Code::kMarkedForDeoptimizationBit, + &found_deoptimized_code); // Optimized code is good, get it into the closure and link the closure into // the optimized functions list, then tail call the optimized code. @@ -1193,8 +1198,11 @@ void Builtins::Generate_InterpreterEntryTrampoline(MacroAssembler* masm) { Label push_stack_frame; // Check if feedback vector is valid. If valid, check for optimized code // and update invocation count. Otherwise, setup the stack frame. - __ CompareRoot(feedback_vector, RootIndex::kUndefinedValue); - __ B(eq, &push_stack_frame); + __ LoadTaggedPointerField( + x7, FieldMemOperand(feedback_vector, HeapObject::kMapOffset)); + __ Ldrh(x7, FieldMemOperand(x7, Map::kInstanceTypeOffset)); + __ Cmp(x7, FEEDBACK_VECTOR_TYPE); + __ B(ne, &push_stack_frame); // Read off the optimized code slot in the feedback vector, and if there // is optimized code or an optimization marker, call that instead. @@ -1217,9 +1225,14 @@ void Builtins::Generate_InterpreterEntryTrampoline(MacroAssembler* masm) { __ Add(fp, sp, StandardFrameConstants::kFixedFrameSizeFromFp); // Reset code age. - __ Mov(x10, Operand(BytecodeArray::kNoAgeBytecodeAge)); - __ Strb(x10, FieldMemOperand(kInterpreterBytecodeArrayRegister, - BytecodeArray::kBytecodeAgeOffset)); + // Reset code age and the OSR arming. The OSR field and BytecodeAgeOffset are + // 8-bit fields next to each other, so we could just optimize by writing a + // 16-bit. These static asserts guard our assumption is valid. + STATIC_ASSERT(BytecodeArray::kBytecodeAgeOffset == + BytecodeArray::kOSRNestingLevelOffset + kCharSize); + STATIC_ASSERT(BytecodeArray::kNoAgeBytecodeAge == 0); + __ Strh(wzr, FieldMemOperand(kInterpreterBytecodeArrayRegister, + BytecodeArray::kOSRNestingLevelOffset)); // Load the initial bytecode offset. __ Mov(kInterpreterBytecodeOffsetRegister, diff --git a/deps/v8/src/builtins/array-join.tq b/deps/v8/src/builtins/array-join.tq index f29f6694d4..8c531141f0 100644 --- a/deps/v8/src/builtins/array-join.tq +++ b/deps/v8/src/builtins/array-join.tq @@ -159,7 +159,7 @@ namespace array_join { this.AddSeparators(nofSeparators, separatorLength, writeSeparators); this.totalStringLength = - AddStringLength(this.totalStringLength, str.length); + AddStringLength(this.totalStringLength, str.length_intptr); this.fixedArray = StoreAndGrowFixedArray(this.fixedArray, this.index++, str); this.isOneByte = @@ -219,10 +219,10 @@ namespace array_join { Signed(len); assert(cappedBufferSize > 0); return Buffer{ - AllocateZeroedFixedArray(cappedBufferSize), - 0, - 0, - IsOneByteStringInstanceType(sep.instanceType) + fixedArray: AllocateZeroedFixedArray(cappedBufferSize), + index: 0, + totalStringLength: 0, + isOneByte: IsOneByteStringInstanceType(sep.instanceType) }; } @@ -265,7 +265,7 @@ namespace array_join { initialLoadFn: LoadJoinElementFn): String { const initialMap: Map = receiver.map; const len: uintptr = Convert<uintptr>(lengthNumber); - const separatorLength: intptr = sep.length; + const separatorLength: intptr = sep.length_intptr; let nofSeparators: intptr = 0; let loadFn: LoadJoinElementFn = initialLoadFn; let buffer: Buffer = NewBuffer(len, sep); diff --git a/deps/v8/src/builtins/array-lastindexof.tq b/deps/v8/src/builtins/array-lastindexof.tq index 2ade54156c..d6213157dc 100644 --- a/deps/v8/src/builtins/array-lastindexof.tq +++ b/deps/v8/src/builtins/array-lastindexof.tq @@ -58,9 +58,8 @@ namespace array_lastindexof { return -1; } - macro GetFromIndex( - context: Context, length: Number, - arguments: constexpr Arguments): Number { + transitioning macro + GetFromIndex(context: Context, length: Number, arguments: Arguments): Number { // 4. If fromIndex is present, let n be ? ToInteger(fromIndex); // else let n be len - 1. const n: Number = arguments.length < 2 ? diff --git a/deps/v8/src/builtins/array-map.tq b/deps/v8/src/builtins/array-map.tq index aa43befb57..7546f1cd00 100644 --- a/deps/v8/src/builtins/array-map.tq +++ b/deps/v8/src/builtins/array-map.tq @@ -173,7 +173,12 @@ namespace array_map { AllocateFixedArrayWithHoles( SmiUntag(length), kAllowLargeObjectAllocation) : kEmptyFixedArray; - return Vector{fixedArray, true, true, false}; + return Vector{ + fixedArray, + onlySmis: true, + onlyNumbers: true, + skippedElements: false + }; } transitioning macro FastArrayMap(implicit context: Context)( diff --git a/deps/v8/src/builtins/array-of.tq b/deps/v8/src/builtins/array-of.tq index 70fda8d2eb..76123207fd 100644 --- a/deps/v8/src/builtins/array-of.tq +++ b/deps/v8/src/builtins/array-of.tq @@ -10,7 +10,7 @@ namespace array_of { const len: Smi = Convert<Smi>(arguments.length); // 2. Let items be the List of arguments passed to this function. - const items: constexpr Arguments = arguments; + const items: Arguments = arguments; // 3. Let C be the this value. const c: Object = receiver; diff --git a/deps/v8/src/builtins/array-shift.tq b/deps/v8/src/builtins/array-shift.tq new file mode 100644 index 0000000000..3c8c1491bb --- /dev/null +++ b/deps/v8/src/builtins/array-shift.tq @@ -0,0 +1,114 @@ +// 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. + +namespace array_shift { + extern builtin ArrayShift(Context, JSFunction, Object, int32); + + macro TryFastArrayShift(implicit context: Context)( + receiver: Object, arguments: Arguments): Object + labels Slow { + const array: FastJSArray = Cast<FastJSArray>(receiver) otherwise Slow; + let witness = NewFastJSArrayWitness(array); + + witness.EnsureArrayPushable() otherwise Slow; + + if (array.length == 0) { + return Undefined; + } + + try { + const newLength = array.length - 1; + + // Check that we're not supposed to right-trim the backing store, as + // implemented in elements.cc:ElementsAccessorBase::SetLengthImpl. + if ((newLength + newLength + kMinAddedElementsCapacity) < + array.elements.length) { + goto Runtime; + } + + // Check that we're not supposed to left-trim the backing store, as + // implemented in elements.cc:FastElementsAccessor::MoveElements. + if (newLength > kMaxCopyElements) goto Runtime; + + const result = witness.LoadElementOrUndefined(0); + witness.ChangeLength(newLength); + witness.MoveElements(0, 1, Convert<intptr>(newLength)); + witness.StoreHole(newLength); + return result; + } + label Runtime { + tail ArrayShift( + context, LoadTargetFromFrame(), Undefined, + Convert<int32>(arguments.length)); + } + } + + transitioning macro GenericArrayShift(implicit context: + Context)(receiver: Object): Object { + // 1. Let O be ? ToObject(this value). + const object: JSReceiver = ToObject_Inline(context, receiver); + + // 2. Let len be ? ToLength(? Get(O, "length")). + const length: Number = GetLengthProperty(object); + + // 3. If len is zero, then + if (length == 0) { + // a. Perform ? Set(O, "length", 0, true). + SetProperty(object, kLengthString, Convert<Smi>(0)); + // b. Return undefined. + return Undefined; + } + + // 4. Let first be ? Get(O, "0"). + const first = GetProperty(object, Convert<Smi>(0)); + // 5. Let k be 1. + let k: Number = 1; + // 6. Repeat, while k < len + while (k < length) { + // a. Let from be ! ToString(k). + const from: Number = k; + + // b. Let to be ! ToString(k - 1). + const to: Number = k - 1; + + // c. Let fromPresent be ? HasProperty(O, from). + const fromPresent: Boolean = HasProperty(object, from); + + // d. If fromPresent is true, then + if (fromPresent == True) { + // i. Let fromVal be ? Get(O, from). + const fromValue: Object = GetProperty(object, from); + + // ii. Perform ? Set(O, to, fromValue, true). + SetProperty(object, to, fromValue); + } else { + // i. Perform ? DeletePropertyOrThrow(O, to). + DeleteProperty(object, to, kStrict); + } + + // f. Increase k by 1. + k++; + } + + // 7. Perform ? DeletePropertyOrThrow(O, ! ToString(len - 1)). + DeleteProperty(object, length - 1, kStrict); + + // 8. Perform ? Set(O, "length", len - 1, true). + SetProperty(object, kLengthString, length - 1); + + // 9. Return first. + return first; + } + + // https://tc39.github.io/ecma262/#sec-array.prototype.shift + transitioning javascript builtin ArrayPrototypeShift( + implicit context: Context)(receiver: Object, ...arguments): Object { + try { + return TryFastArrayShift(receiver, arguments) otherwise Slow; + } + label Slow { + return GenericArrayShift(receiver); + } + } +} diff --git a/deps/v8/src/builtins/array-splice.tq b/deps/v8/src/builtins/array-splice.tq index 586630cd39..e24b51760c 100644 --- a/deps/v8/src/builtins/array-splice.tq +++ b/deps/v8/src/builtins/array-splice.tq @@ -53,7 +53,7 @@ namespace array_splice { macro FastSplice<FixedArrayType: type, ElementType: type>(implicit context: Context)( - args: constexpr Arguments, a: JSArray, length: Smi, newLength: Smi, + args: Arguments, a: JSArray, length: Smi, newLength: Smi, lengthDelta: Smi, actualStart: Smi, insertCount: Smi, actualDeleteCount: Smi): void labels Bailout { // Make sure elements are writable. @@ -95,7 +95,8 @@ namespace array_splice { if (insertCount > 0) { const typedNewElements: FixedArrayType = UnsafeCast<FixedArrayType>(a.elements); - for (let e: Object of args [2: ]) { + for (let i: intptr = 2; i < args.length; ++i) { + const e: Object = args[i]; // The argument elements were already validated to be an appropriate // {ElementType} to store in {FixedArrayType}. typedNewElements[k++] = UnsafeCast<ElementType>(e); @@ -107,7 +108,7 @@ namespace array_splice { } transitioning macro FastArraySplice( - context: Context, args: constexpr Arguments, o: JSReceiver, + context: Context, args: Arguments, o: JSReceiver, originalLengthNumber: Number, actualStartNumber: Number, insertCount: Smi, actualDeleteCountNumber: Number): Object labels Bailout { @@ -131,7 +132,8 @@ namespace array_splice { if (!IsFastElementsKind(elementsKind)) goto Bailout; const oldElementsKind: ElementsKind = elementsKind; - for (let e: Object of args [2: ]) { + for (let i: intptr = 2; i < args.length; ++i) { + const e: Object = args[i]; if (IsFastSmiElementsKind(elementsKind)) { if (TaggedIsNotSmi(e)) { const heapObject: HeapObject = UnsafeCast<HeapObject>(e); @@ -296,8 +298,8 @@ namespace array_splice { } transitioning macro SlowSplice( - context: Context, arguments: constexpr Arguments, o: JSReceiver, - len: Number, actualStart: Number, insertCount: Smi, + context: Context, arguments: Arguments, o: JSReceiver, len: Number, + actualStart: Number, insertCount: Smi, actualDeleteCount: Number): Object { const affected: Number = len - actualStart - actualDeleteCount; @@ -332,7 +334,8 @@ namespace array_splice { // a. Remove the first element from items and let E be the value of that // element. if (arguments.length > 2) { - for (let e: Object of arguments [2: ]) { + for (let i: intptr = 2; i < arguments.length; ++i) { + const e: Object = arguments[i]; // b. Perform ? Set(O, ! ToString(k), E, true). SetProperty(o, k, e); diff --git a/deps/v8/src/builtins/array-unshift.tq b/deps/v8/src/builtins/array-unshift.tq index b193e751fd..b2e746db47 100644 --- a/deps/v8/src/builtins/array-unshift.tq +++ b/deps/v8/src/builtins/array-unshift.tq @@ -6,7 +6,7 @@ namespace array_unshift { extern builtin ArrayUnshift(Context, JSFunction, Object, int32); macro TryFastArrayUnshift( - context: Context, receiver: Object, arguments: constexpr Arguments): never + context: Context, receiver: Object, arguments: Arguments): never labels Slow { const array: FastJSArray = Cast<FastJSArray>(receiver) otherwise Slow; array::EnsureWriteableFastElements(array); @@ -21,8 +21,7 @@ namespace array_unshift { } transitioning macro GenericArrayUnshift( - context: Context, receiver: Object, - arguments: constexpr Arguments): Number { + context: Context, receiver: Object, arguments: Arguments): Number { // 1. Let O be ? ToObject(this value). const object: JSReceiver = ToObject_Inline(context, receiver); diff --git a/deps/v8/src/builtins/base.tq b/deps/v8/src/builtins/base.tq index da5f072a21..dd061acf81 100644 --- a/deps/v8/src/builtins/base.tq +++ b/deps/v8/src/builtins/base.tq @@ -10,12 +10,14 @@ #include 'src/objects.h' #include 'src/objects/arguments.h' #include 'src/objects/bigint.h' +#include 'src/objects/free-space.h' #include 'src/objects/js-generator.h' #include 'src/objects/js-promise.h' +#include 'src/objects/js-regexp-string-iterator.h' #include 'src/objects/module.h' #include 'src/objects/stack-frame-info.h' +#include 'src/builtins/builtins-regexp-gen.h' -type Arguments constexpr 'CodeStubArguments*'; type void; type never; @@ -38,12 +40,12 @@ type int31 extends int32 type uint31 extends uint32 generates 'TNode<Uint32T>' constexpr 'uint31_t'; type int16 extends int31 - generates 'TNode<Int32T>' constexpr 'int16_t'; + generates 'TNode<Int16T>' constexpr 'int16_t'; type uint16 extends uint31 - generates 'TNode<Uint32T>' constexpr 'uint16_t'; -type int8 extends int16 generates 'TNode<Int32T>' constexpr 'int8_t'; + generates 'TNode<Uint16T>' constexpr 'uint16_t'; +type int8 extends int16 generates 'TNode<Int8T>' constexpr 'int8_t'; type uint8 extends uint16 - generates 'TNode<Uint32T>' constexpr 'uint8_t'; + generates 'TNode<Uint8T>' constexpr 'uint8_t'; type int64 generates 'TNode<Int64T>' constexpr 'int64_t'; type intptr generates 'TNode<IntPtrT>' constexpr 'intptr_t'; type uintptr generates 'TNode<UintPtrT>' constexpr 'uintptr_t'; @@ -54,26 +56,80 @@ type bint generates 'TNode<BInt>' constexpr 'BInt'; type string constexpr 'const char*'; type RawPtr generates 'TNode<RawPtrT>' constexpr 'void*'; -type AbstractCode extends HeapObject generates 'TNode<AbstractCode>'; -type Code extends AbstractCode generates 'TNode<Code>'; +type Code extends HeapObject generates 'TNode<Code>'; type BuiltinPtr extends Smi generates 'TNode<BuiltinPtr>'; -type Context extends HeapObject generates 'TNode<Context>'; +extern class Context extends HeapObject { + length: Smi; + scope_info: ScopeInfo; + previous: Object; + extension: Object; + native_context: Object; +} type NativeContext extends Context; -type String extends HeapObject generates 'TNode<String>'; -type Oddball extends HeapObject generates 'TNode<Oddball>'; -type HeapNumber extends HeapObject generates 'TNode<HeapNumber>'; +extern class Oddball extends HeapObject { + to_number_raw: float64; + to_string: String; + to_number: Number; + type_of: String; + kind: Smi; +} +extern class HeapNumber extends HeapObject { value: float64; } type Number = Smi | HeapNumber; type BigInt extends HeapObject generates 'TNode<BigInt>'; type Numeric = Number | BigInt; +extern class Name extends HeapObject { hash_field: int32; } + +extern class Symbol extends Name { + flags: int32; + name: Object; +} + +// abstract +extern class String extends Name { length: uint32; } + +extern class ConsString extends String { + first: String; + second: String; +} + +extern class ExternalString extends String { + resource: RawPtr; + resource_data: RawPtr; +} + +extern class ExternalOneByteString extends ExternalString {} +extern class ExternalTwoByteString extends ExternalString {} + +extern class InternalizedString extends String {} + +// TODO(v8:8983): Add declaration for variable-sized region. +extern class SeqString extends String {} +extern class SeqOneByteString extends SeqString {} +extern class SeqTwoByteString extends SeqString {} + +extern class SlicedString extends String { + parent: String; + offset: Smi; +} + +extern class ThinString extends String { actual: String; } + +// The HeapNumber value NaN +type NaN extends HeapNumber; + extern class Struct extends HeapObject {} +@generatePrint extern class Tuple2 extends Struct { - value_1: Object; - value_2: Object; + value1: Object; + value2: Object; } -extern class Tuple3 extends Tuple2 { value_3: Object; } +@generatePrint +extern class Tuple3 extends Tuple2 { + value3: Object; +} // A direct string can be accessed directly through CSA without going into the // C++ runtime. See also: ToDirectStringAssembler. @@ -91,6 +147,18 @@ extern class FixedDoubleArray extends FixedArrayBase { floats[length]: float64; } +extern class WeakFixedArray extends HeapObject { length: Smi; } + +extern class ByteArray extends FixedArrayBase {} + +type BytecodeArray extends FixedArrayBase; + +@generatePrint +extern class EnumCache extends Struct { + keys: FixedArray; + indices: FixedArray; +} + // These intrinsics should never be called from Torque code. They're used // internally by the 'new' operator and only declared here because it's simpler // than building the definition from C++. @@ -109,13 +177,25 @@ extern class JSObject extends JSReceiver { elements: FixedArrayBase; } macro NewJSObject( map: Map, properties: FixedArrayBase | Smi, elements: FixedArrayBase): JSObject { - return new JSObject{map, properties, elements}; + return new JSObject{map, properties_or_hash: properties, elements}; } macro NewJSObject(implicit context: Context)(): JSObject { const objectFunction: JSFunction = GetObjectFunction(); const map: Map = Cast<Map>(objectFunction.prototype_or_initial_map) otherwise unreachable; - return new JSObject{map, kEmptyFixedArray, kEmptyFixedArray}; + return new JSObject{ + map, + properties_or_hash: kEmptyFixedArray, + elements: kEmptyFixedArray + }; +} + +extern class JSFunction extends JSObject { + shared_function_info: SharedFunctionInfo; + context: Context; + feedback_cell: Smi; + weak code: Code; + weak prototype_or_initial_map: JSReceiver | Map; } extern class JSProxy extends JSReceiver { @@ -128,11 +208,34 @@ extern class JSProxyRevocableResult extends JSObject { revoke: Object; } +macro NewJSProxyRevocableResult(implicit context: Context)( + proxy: JSProxy, revoke: JSFunction): JSProxyRevocableResult { + return new JSProxyRevocableResult{ + map: GetProxyRevocableResultMap(), + properties_or_hash: kEmptyFixedArray, + elements: kEmptyFixedArray, + proxy, + revoke + }; +} + extern class JSGlobalProxy extends JSObject { native_context: Object; } extern class JSValue extends JSObject { value: Object; } -extern class JSArgumentsObjectWithLength extends JSObject { length: Object; } +extern class JSArgumentsObject extends JSObject {} +extern class JSArgumentsObjectWithLength extends JSArgumentsObject { + length: Object; +} +extern class JSSloppyArgumentsObject extends JSArgumentsObjectWithLength { + callee: Object; +} + +extern class JSArrayIterator extends JSObject { + iterated_object: JSReceiver; + next_index: Number; + kind: Smi; +} extern class JSArray extends JSObject { IsEmpty(): bool { @@ -143,18 +246,37 @@ extern class JSArray extends JSObject { macro NewJSArray(implicit context: Context)( map: Map, elements: FixedArrayBase): JSArray { - return new JSArray{map, kEmptyFixedArray, elements, elements.length}; + return new JSArray{ + map, + properties_or_hash: kEmptyFixedArray, + elements, + length: elements.length + }; } macro NewJSArray(implicit context: Context)(): JSArray { return new JSArray{ - GetFastPackedSmiElementsJSArrayMap(), - kEmptyFixedArray, - kEmptyFixedArray, - 0 + map: GetFastPackedSmiElementsJSArrayMap(), + properties_or_hash: kEmptyFixedArray, + elements: kEmptyFixedArray, + length: 0 }; } +struct HoleIterator { + Next(): Object labels NoMore() { + return Hole; + } +} + +macro NewJSArray(implicit context: Context)(map: Map, length: Smi): JSArray { + const map = GetFastPackedSmiElementsJSArrayMap(); + const i = HoleIterator{}; + const elements = new FixedArray{map, length, objects: ...i}; + return new + JSArray{map, properties_or_hash: kEmptyFixedArray, elements, length}; +} + // A HeapObject with a JSArray map, and either fast packed elements, or fast // holey elements when the global NoElementsProtector is not invalidated. transient type FastJSArray extends JSArray; @@ -166,11 +288,75 @@ transient type FastJSArrayForCopy extends FastJSArray; transient type FastJSArrayWithNoCustomIteration extends FastJSArray; type NoSharedNameSentinel extends Smi; -type Script extends HeapObject; + +type JSModuleNamespace extends JSObject; +type WeakArrayList extends HeapObject; + +extern class JSWeakCollection extends JSObject { table: Object; } +extern class JSWeakSet extends JSWeakCollection {} +extern class JSWeakMap extends JSWeakCollection {} + +extern class JSCollectionIterator extends JSObject { + table: Object; + index: Object; +} + +extern class JSMessageObject extends JSObject { + // Tagged fields. + message_type: Smi; + arguments: Object; + script: Script; + stack_frames: Object; + // Raw data fields. + // TODO(ishell): store as int32 instead of Smi. + start_position: Smi; + end_position: Smi; + error_level: Smi; +} + +extern class PrototypeInfo extends Struct { + js_module_namespace: JSModuleNamespace | Undefined; + prototype_users: WeakArrayList | Zero; + registry_slot: Smi; + validity_cell: Object; + object_create_map: Smi | WeakArrayList; + bit_field: Smi; +} + +extern class Script extends Struct { + source: Object; + name: Object; + line_offset: Smi; + column_offset: Smi; + context: Object; + script_type: Smi; + line_ends: Object; + id: Smi; + eval_from_shared_or_wrapped_arguments: Object; + eval_from_position: Smi; + shared_function_infos: Object; + flags: Smi; + source_url: Object; + source_mapping_url: Object; + host_defined_options: Object; +} type DebugInfo extends HeapObject; +extern class EmbedderDataArray extends HeapObject { length: Smi; } + type ScopeInfo extends Object generates 'TNode<ScopeInfo>'; +extern class PreparseData extends HeapObject { + // TODO(v8:8983): Add declaration for variable-sized region. + data_length: int32; + inner_length: int32; +} + +extern class InterpreterData extends Struct { + bytecode_array: BytecodeArray; + interpreter_trampoline: Code; +} + extern class SharedFunctionInfo extends HeapObject { weak function_data: Object; name_or_scope_info: String | NoSharedNameSentinel | ScopeInfo; @@ -178,8 +364,8 @@ extern class SharedFunctionInfo extends HeapObject { script_or_debug_info: Script | DebugInfo; length: int16; formal_parameter_count: uint16; - expected_nof_properties: int8; - builtin_function_id: int8; + // Currently set to uint16, can be set to uint8 to save space. + expected_nof_properties: uint16; function_token_offset: int16; flags: int32; } @@ -188,14 +374,6 @@ extern class SharedFunctionInfoWithID extends SharedFunctionInfo { unique_id: int32; } -extern class JSFunction extends JSObject { - shared_function_info: SharedFunctionInfo; - context: Context; - feedback_cell: Smi; - weak code: Code; - weak prototype_or_initial_map: JSReceiver | Map; -} - extern class JSBoundFunction extends JSObject { bound_target_function: JSReceiver; bound_this: Object; @@ -218,6 +396,11 @@ extern class SloppyArgumentsElements extends FixedArray {} type NumberDictionary extends HeapObject generates 'TNode<NumberDictionary>'; +extern class FreeSpace extends HeapObject { + size: Smi; + next: FreeSpace; +} + // %RawDownCast should *never* be used anywhere in Torque code except for // in Torque-based UnsafeCast operators preceeded by an appropriate // type assert() @@ -239,11 +422,20 @@ const ITERATOR_RESULT_MAP_INDEX: constexpr NativeContextSlot generates 'Context::ITERATOR_RESULT_MAP_INDEX'; const JS_ARRAY_PACKED_SMI_ELEMENTS_MAP_INDEX: constexpr NativeContextSlot generates 'Context::JS_ARRAY_PACKED_SMI_ELEMENTS_MAP_INDEX'; +const PROXY_REVOCABLE_RESULT_MAP_INDEX: constexpr NativeContextSlot + generates 'Context::PROXY_REVOCABLE_RESULT_MAP_INDEX'; extern operator '[]' macro LoadContextElement( NativeContext, NativeContextSlot): Object; extern operator '[]=' macro StoreContextElement( NativeContext, NativeContextSlot, Object): void; +type ContextSlot generates 'TNode<IntPtrT>' constexpr 'int32_t'; +const PROXY_SLOT: constexpr ContextSlot + generates 'Context::MIN_CONTEXT_SLOTS'; +extern operator '[]' macro LoadContextElement(Context, ContextSlot): Object; +extern operator '[]=' macro StoreContextElement( + Context, ContextSlot, Object): void; + extern operator '[]' macro LoadContextElement(Context, intptr): Object; extern operator '[]' macro LoadContextElement(Context, Smi): Object; @@ -280,8 +472,12 @@ extern class JSTypedArray extends JSArrayBufferView { Convert<uintptr>(externalPointer) >= Convert<uintptr>(backingStore)); this.buffer = buffer; - this.elements = new - FixedTypedArrayBase{map, length, basePointer, externalPointer}; + this.elements = new FixedTypedArrayBase{ + map, + length, + base_pointer: basePointer, + external_pointer: externalPointer + }; } length: Smi; @@ -295,8 +491,85 @@ extern class JSAccessorPropertyDescriptor extends JSObject { } extern class JSCollection extends JSObject { table: Object; } +extern class JSSet extends JSCollection {} +extern class JSMap extends JSCollection {} + +extern class JSDate extends JSObject { + value: NumberOrUndefined; + year: Undefined | Smi | NaN; + month: Undefined | Smi | NaN; + day: Undefined | Smi | NaN; + weekday: Undefined | Smi | NaN; + hour: Undefined | Smi | NaN; + min: Undefined | Smi | NaN; + sec: Undefined | Smi | NaN; + cache_stamp: Undefined | Smi | NaN; +} + +extern class JSAsyncFromSyncIterator extends JSObject { + sync_iterator: JSReceiver; + next: Object; +} -type JSDataView extends JSArrayBufferView generates 'TNode<JSDataView>'; +extern class JSStringIterator extends JSObject { + string: String; + next_index: Smi; +} + +extern class JSDataPropertyDescriptor extends JSObject { + value: Object; + writable: Object; + enumerable: Object; + configurable: Object; +} + +extern class TemplateInfo extends Struct { + tag: Object; + serial_number: Object; + number_of_properties: Smi; + property_list: Object; + property_accessors: Object; +} + +extern class FunctionTemplateRareData extends Struct { + prototype_template: Object; + prototype_provider_template: Object; + parent_template: Object; + named_property_handler: Object; + indexed_property_handler: Object; + instance_template: Object; + instance_call_handler: Object; + access_check_info: Object; +} + +extern class FunctionTemplateInfo extends TemplateInfo { + call_code: Object; + class_name: Object; + signature: Object; + function_template_rare_data: Object; + shared_function_info: Object; + flag: Smi; + length: Smi; + cached_property_name: Object; +} + +extern class ObjectTemplateInfo extends TemplateInfo { + constructor: Object; + data: Object; +} + +extern class PropertyArray extends HeapObject { length_and_hash: Smi; } + +extern class DependentCode extends WeakFixedArray {} + +extern class PropertyCell extends HeapObject { + name: Name; + property_details_raw: Smi; + value: Object; + dependent_code: DependentCode; +} + +extern class JSDataView extends JSArrayBufferView {} type InstanceType generates 'TNode<Int32T>' constexpr 'InstanceType'; type ElementsKind generates 'TNode<Int32T>' constexpr 'ElementsKind'; @@ -352,6 +625,25 @@ extern class DataHandler extends Struct { weak data_3: Object; } +extern class JSGeneratorObject extends JSObject { + function: JSFunction; + context: Context; + receiver: Object; + input_or_debug_pos: Object; + resume_mode: Smi; + continuation: Smi; + parameters_and_registers: FixedArray; +} + +extern class JSAsyncFunctionObject extends JSGeneratorObject { + promise: JSPromise; +} + +extern class JSAsyncGeneratorObject extends JSGeneratorObject { + queue: HeapObject; + is_awaiting: Smi; +} + extern class JSPromise extends JSObject { reactions_or_result: Object; flags: Smi; @@ -377,6 +669,12 @@ extern class StackFrameInfo extends Struct { script_name_or_source_url: Object; function_name: Object; flag: Smi; +} + +extern class StackTraceFrame extends Struct { + frame_array: Object; + frame_index: Smi; + frame_info: Object; id: Smi; } @@ -385,9 +683,28 @@ extern class ClassPositions extends Struct { end: Smi; } +type WasmInstanceObject extends JSObject; + +extern class WasmExportedFunctionData extends Struct { + wrapper_code: Code; + instance: WasmInstanceObject; + jump_table_offset: Smi; + function_index: Smi; +} + +extern class WasmDebugInfo extends Struct { + instance: WasmInstanceObject; + interpreter_handle: Foreign | Undefined; + interpreted_functions: FixedArray; + locals_names: FixedArray; + c_wasm_entries: FixedArray; + c_wasm_entry_map: Foreign; // Managed<wasm::SignatureMap> +} + extern class WasmExceptionTag extends Struct { index: Smi; } const kSmiTagSize: constexpr int31 generates 'kSmiTagSize'; +const V8_INFINITY: constexpr float64 generates 'V8_INFINITY'; const NO_ELEMENTS: constexpr ElementsKind generates 'NO_ELEMENTS'; @@ -452,6 +769,8 @@ const kAllFixedArrays: constexpr ExtractFixedArrayFlags const kFixedArrays: constexpr ExtractFixedArrayFlags generates 'CodeStubAssembler::ExtractFixedArrayFlag::kFixedArrays'; +const kFixedArrayMapRootIndex: + constexpr RootIndex generates 'RootIndex::kFixedArrayMap'; const kFixedCOWArrayMapRootIndex: constexpr RootIndex generates 'RootIndex::kFixedCOWArrayMap'; const kEmptyFixedArrayRootIndex: @@ -485,6 +804,14 @@ const kBigIntMixedTypes: constexpr MessageTemplate generates 'MessageTemplate::kBigIntMixedTypes'; const kTypedArrayTooShort: constexpr MessageTemplate generates 'MessageTemplate::kTypedArrayTooShort'; +const kInvalidCountValue: constexpr MessageTemplate + generates 'MessageTemplate::kInvalidCountValue'; +const kProxyNonObject: constexpr MessageTemplate + generates 'MessageTemplate::kProxyNonObject'; +const kProxyHandlerOrTargetRevoked: constexpr MessageTemplate + generates 'MessageTemplate::kProxyHandlerOrTargetRevoked'; +const kConstructorNotFunction: constexpr MessageTemplate + generates 'MessageTemplate::kConstructorNotFunction'; const kMaxArrayIndex: constexpr uint32 generates 'JSArray::kMaxArrayIndex'; @@ -501,7 +828,10 @@ const kFixedTypedArrayBaseHeaderSize: constexpr intptr generates 'FixedTypedArrayBase::kHeaderSize'; const kObjectAlignmentMask: constexpr intptr generates 'kObjectAlignmentMask'; - +const kMinAddedElementsCapacity: + constexpr int31 generates 'JSObject::kMinAddedElementsCapacity'; +const kMaxCopyElements: + constexpr int31 generates 'JSArray::kMaxCopyElements'; const kMaxRegularHeapObjectSize: constexpr int31 generates 'kMaxRegularHeapObjectSize'; @@ -603,6 +933,139 @@ extern class PromiseReaction extends Struct { promise_or_capability: JSPromise | PromiseCapability | Undefined; } +extern class PromiseReactionJobTask extends Microtask { + argument: Object; + context: Context; + handler: Callable | Undefined; + promise_or_capability: JSPromise | PromiseCapability | Undefined; +} + +extern class PromiseFulfillReactionJobTask extends PromiseReactionJobTask {} + +extern class PromiseRejectReactionJobTask extends PromiseReactionJobTask {} + +extern class PromiseResolveThenableJobTask extends Microtask { + context: Context; + promise_to_resolve: JSPromise; + then: JSReceiver; + thenable: JSReceiver; +} + +extern class JSRegExp extends JSObject { + data: FixedArray | Undefined; + source: String | Undefined; + flags: Smi | Undefined; +} + +// Note: Although a condition for a FastJSRegExp is having a positive smi +// lastIndex (see RegExpBuiltinsAssembler::BranchIfFastRegExp), it is possible +// for this to change without transitioning the transient type. As a precaution, +// validate the lastIndex is positive smi when used in fast paths. +transient type FastJSRegExp extends JSRegExp; + +extern operator '.global' macro +RegExpBuiltinsAssembler::FastFlagGetterGlobal(FastJSRegExp): bool; +extern operator '.unicode' macro +RegExpBuiltinsAssembler::FastFlagGetterUnicode(FastJSRegExp): bool; +extern operator '.lastIndex' macro +RegExpBuiltinsAssembler::FastLoadLastIndex(FastJSRegExp): Smi; +extern operator '.lastIndex=' macro +RegExpBuiltinsAssembler::FastStoreLastIndex(FastJSRegExp, Smi): void; + +extern class JSRegExpResult extends JSArray { + index: Object; + input: Object; + groups: Object; +} + +extern class JSRegExpStringIterator extends JSObject { + iterating_reg_exp: Object; + iterated_string: String; + flags: Smi; +} + +const kRegExpMatchInfoFirstCaptureIndex: + constexpr int31 generates 'RegExpMatchInfo::kFirstCaptureIndex'; +macro GetStartOfCaptureIndex(captureIndex: constexpr int31): constexpr int31 { + return kRegExpMatchInfoFirstCaptureIndex + (captureIndex * 2); +} + +extern class RegExpMatchInfo extends FixedArray { + GetStartOfCapture(implicit context: Context)(captureIndex: constexpr int31): + Smi { + const index: constexpr int31 = GetStartOfCaptureIndex(captureIndex); + return UnsafeCast<Smi>(this.objects[index]); + } + GetEndOfCapture(implicit context: Context)(captureIndex: constexpr int31): + Smi { + const index: constexpr int31 = GetStartOfCaptureIndex(captureIndex) + 1; + return UnsafeCast<Smi>(this.objects[index]); + } +} + +extern class AccessorInfo extends Struct { + name: Object; + flags: Smi; + expected_receiver_type: Object; + setter: Foreign | Zero; + getter: Foreign | Zero; + js_getter: Foreign | Zero; + data: Object; +} + +extern class AccessorPair extends Struct { + getter: Object; + setter: Object; +} + +extern class BreakPoint extends Tuple2 {} +extern class BreakPointInfo extends Tuple2 {} + +extern class WasmModuleObject extends JSObject { + native_module: Foreign; + export_wrappers: FixedArray; + script: Script; + weak_instance_list: WeakArrayList; + asm_js_offset_table: ByteArray; + break_point_infos: FixedArray; +} + +extern class WasmTableObject extends JSObject { + elements: FixedArray; + maximum_length: Smi | HeapNumber | Undefined; + dispatch_tables: FixedArray; + raw_type: Smi; +} + +extern class WasmMemoryObject extends JSObject { + array_buffer: JSArrayBuffer; + maximum_pages: Smi; + instances: WeakArrayList; +} + +extern class WasmGlobalObject extends JSObject { + untagged_buffer: JSArrayBuffer; + tagged_buffer: FixedArray; + offset: Smi; + flags: Smi; +} + +extern class WasmExceptionObject extends JSObject { + serialized_signature: ByteArray; // PodArray<wasm::ValueType> + exception_tag: HeapObject; +} + +extern class WasmExceptionPackage extends JSReceiver {} + +extern class WasmExportedFunction extends JSFunction {} + +extern class AsmWasmData extends Struct { + managed_native_module: Foreign; // Managed<wasm::NativeModule> + export_wrappers: FixedArray; + asm_js_offset_table: ByteArray; + uses_bitset: HeapNumber; +} + extern macro Is64(): constexpr bool; extern macro SelectBooleanConstant(bool): Boolean; @@ -612,16 +1075,18 @@ extern macro Print(constexpr string, Object); extern macro Comment(constexpr string); extern macro Print(Object); extern macro DebugBreak(); -extern macro ToInteger_Inline(Context, Object): Number; -extern macro ToInteger_Inline( +extern transitioning macro ToInteger_Inline(Context, Object): Number; +extern transitioning macro ToInteger_Inline( Context, Object, constexpr ToIntegerTruncationMode): Number; -extern macro ToLength_Inline(Context, Object): Number; -extern macro ToNumber_Inline(Context, Object): Number; -extern macro ToSmiIndex(implicit context: Context)(Object): PositiveSmi - labels IfRangeError; -extern macro ToSmiLength(implicit context: Context)(Object): PositiveSmi - labels IfRangeError; -extern macro ToString_Inline(Context, Object): String; +extern transitioning macro ToLength_Inline(Context, Object): Number; +extern transitioning macro ToNumber_Inline(Context, Object): Number; +extern transitioning macro ToSmiIndex(implicit context: Context)(Object): + PositiveSmi labels IfRangeError; +extern transitioning macro ToSmiLength(implicit context: Context)(Object): + PositiveSmi labels IfRangeError; +extern transitioning macro ToString_Inline(Context, Object): String; +extern transitioning macro ToThisString(implicit context: Context)( + Object, String): String; extern transitioning macro GetProperty(implicit context: Context)( Object, Object): Object; extern transitioning builtin SetProperty(implicit context: Context)( @@ -761,6 +1226,7 @@ extern operator '~' macro ConstexprWordNot(constexpr uintptr): extern operator '==' macro Float64Equal(float64, float64): bool; extern operator '!=' macro Float64NotEqual(float64, float64): bool; extern operator '>' macro Float64GreaterThan(float64, float64): bool; +extern operator '<' macro Float64LessThan(float64, float64): bool; extern macro BranchIfNumberEqual(Number, Number): never labels Taken, NotTaken; @@ -828,6 +1294,10 @@ extern operator '|' macro WordOr(uintptr, uintptr): uintptr; extern operator '+' macro Int32Add(int32, int32): int32; extern operator '+' macro ConstexprUint32Add( constexpr uint32, constexpr int32): constexpr uint32; +extern operator '+' macro ConstexprInt31Add( + constexpr int31, constexpr int31): constexpr int31; +extern operator '*' macro ConstexprInt31Mul( + constexpr int31, constexpr int31): constexpr int31; extern operator '-' macro Int32Sub(int32, int32): int32; extern operator '*' macro Int32Mul(int32, int32): int32; extern operator '%' macro Int32Mod(int32, int32): int32; @@ -886,12 +1356,16 @@ extern operator '!' macro IsFalse(Boolean): bool; extern operator '.instanceType' macro LoadInstanceType(HeapObject): InstanceType; -extern operator '.length' macro LoadStringLengthAsWord(String): intptr; +extern operator '.length_intptr' macro LoadStringLengthAsWord(String): intptr; +extern operator '.length_uint32' macro LoadStringLengthAsWord32(String): uint32; extern operator '.length_smi' macro LoadStringLengthAsSmi(String): Smi; -extern operator '.length' macro GetArgumentsLength(constexpr Arguments): intptr; -extern operator '[]' macro GetArgumentValue( - constexpr Arguments, intptr): Object; +extern builtin StringAdd_CheckNone(implicit context: Context)( + String, String): String; +operator '+' macro StringAdd(implicit context: Context)( + a: String, b: String): String { + return StringAdd_CheckNone(a, b); +} extern macro TaggedIsSmi(Object): bool; extern macro TaggedIsNotSmi(Object): bool; @@ -900,6 +1374,8 @@ extern macro IsValidPositiveSmi(intptr): bool; extern macro HeapObjectToJSDataView(HeapObject): JSDataView labels CastError; +extern macro HeapObjectToJSProxy(HeapObject): JSProxy + labels CastError; extern macro HeapObjectToJSArrayBuffer(HeapObject): JSArrayBuffer labels CastError; extern macro TaggedToHeapObject(Object): HeapObject @@ -979,6 +1455,11 @@ Cast<JSDataView>(o: HeapObject): JSDataView return HeapObjectToJSDataView(o) otherwise CastError; } +Cast<JSProxy>(o: HeapObject): JSProxy + labels CastError { + return HeapObjectToJSProxy(o) otherwise CastError; +} + Cast<JSTypedArray>(o: HeapObject): JSTypedArray labels CastError { if (IsJSTypedArray(o)) return %RawDownCast<JSTypedArray>(o); @@ -1057,6 +1538,12 @@ Cast<HeapNumber>(o: HeapObject): HeapNumber goto CastError; } +Cast<JSRegExp>(o: HeapObject): JSRegExp + labels CastError { + if (IsJSRegExp(o)) return %RawDownCast<JSRegExp>(o); + goto CastError; +} + Cast<Map>(implicit context: Context)(o: HeapObject): Map labels CastError { if (IsMap(o)) return %RawDownCast<Map>(o); @@ -1079,6 +1566,12 @@ Cast<JSArgumentsObjectWithLength>(implicit context: Context)(o: HeapObject): } } +Cast<FastJSRegExp>(implicit context: Context)(o: HeapObject): FastJSRegExp + labels CastError { + if (regexp::BranchIfFastRegExp(o)) return %RawDownCast<FastJSRegExp>(o); + goto CastError; +} + Cast<FastJSArray>(implicit context: Context)(o: HeapObject): FastJSArray labels CastError { const map: Map = o.map; @@ -1144,7 +1637,6 @@ extern macro SmiFromInt32(int32): Smi; extern macro SmiUntag(Smi): intptr; extern macro SmiToInt32(Smi): int32; extern macro RoundIntPtrToFloat64(intptr): float64; -extern macro LoadHeapNumberValue(HeapNumber): float64; extern macro ChangeFloat32ToFloat64(float32): float64; extern macro ChangeNumberToFloat64(Number): float64; extern macro ChangeFloat64ToUintPtr(float64): uintptr; @@ -1176,7 +1668,9 @@ extern macro StringConstant(constexpr string): String; extern macro LanguageModeConstant(constexpr LanguageMode): LanguageMode; extern macro Int32Constant(constexpr ElementsKind): ElementsKind; extern macro IntPtrConstant(constexpr NativeContextSlot): NativeContextSlot; +extern macro IntPtrConstant(constexpr ContextSlot): ContextSlot; extern macro IntPtrConstant(constexpr intptr): intptr; +extern macro SingleCharacterStringConstant(constexpr string): String; extern macro BitcastWordToTaggedSigned(intptr): Smi; extern macro BitcastWordToTaggedSigned(uintptr): Smi; @@ -1265,6 +1759,10 @@ FromConstexpr<NativeContextSlot, constexpr NativeContextSlot>( c: constexpr NativeContextSlot): NativeContextSlot { return IntPtrConstant(c); } +FromConstexpr<ContextSlot, constexpr ContextSlot>(c: constexpr ContextSlot): + ContextSlot { + return IntPtrConstant(c); +} macro Convert<To: type, From: type>(i: From): To { return i; @@ -1398,6 +1896,8 @@ UnsafeCast<Object>(o: Object): Object { return o; } +const kFixedArrayMap: Map = + %RawDownCast<Map>(LoadRoot(kFixedArrayMapRootIndex)); const kCOWMap: Map = %RawDownCast<Map>(LoadRoot(kFixedCOWArrayMapRootIndex)); const kEmptyFixedArray: FixedArray = %RawDownCast<FixedArray>(LoadRoot(kEmptyFixedArrayRootIndex)); @@ -1421,6 +1921,11 @@ extern operator '.elements_kind' macro LoadElementsKind(JSTypedArray): ElementsKind; extern operator '.length' macro LoadFastJSArrayLength(FastJSArray): Smi; +operator '.length=' macro StoreFastJSArrayLength( + array: FastJSArray, length: Smi) { + const array: JSArray = array; + array.length = length; +} extern operator '.objects[]' macro LoadFixedArrayElement( FixedArray, intptr): Object; @@ -1556,6 +2061,11 @@ macro GetFastPackedSmiElementsJSArrayMap(implicit context: Context)(): Map { LoadNativeContext(context)[JS_ARRAY_PACKED_SMI_ELEMENTS_MAP_INDEX]); } +macro GetProxyRevocableResultMap(implicit context: Context)(): Map { + return UnsafeCast<Map>( + LoadNativeContext(context)[PROXY_REVOCABLE_RESULT_MAP_INDEX]); +} + extern transitioning macro Call(Context, Callable, Object): Object; extern transitioning macro Call(Context, Callable, Object, Object): Object; extern transitioning macro Call( @@ -1581,6 +2091,11 @@ extern builtin ExtractFastJSArray(Context, JSArray, Smi, Smi): JSArray; extern macro MoveElements( constexpr ElementsKind, FixedArrayBase, intptr, intptr, intptr): void; +macro TorqueMoveElementsSmi( + elements: FixedArray, dstIndex: intptr, srcIndex: intptr, + count: intptr): void { + MoveElements(HOLEY_SMI_ELEMENTS, elements, dstIndex, srcIndex, count); +} macro TorqueMoveElements( elements: FixedArray, dstIndex: intptr, srcIndex: intptr, count: intptr): void { @@ -1671,6 +2186,18 @@ struct FastJSArrayWitness { } } + StoreHole(k: Smi) { + if (this.hasDoubles) { + const elements = Cast<FixedDoubleArray>(this.unstable.elements) + otherwise unreachable; + StoreFixedDoubleArrayHoleSmi(elements, k); + } else { + const elements = Cast<FixedArray>(this.unstable.elements) + otherwise unreachable; + StoreFixedArrayElementSmi(elements, k, Hole, SKIP_WRITE_BARRIER); + } + } + LoadElementOrUndefined(implicit context: Context)(k: Smi): Object { try { return this.LoadElementNoHole(k) otherwise FoundHole; @@ -1680,11 +2207,17 @@ struct FastJSArrayWitness { } } - EnsureArrayPushable() labels Failed { + EnsureArrayPushable(implicit context: Context)() labels Failed { EnsureArrayPushable(this.map) otherwise Failed; + array::EnsureWriteableFastElements(this.unstable); this.arrayIsPushable = true; } + ChangeLength(newLength: Smi) { + assert(this.arrayIsPushable); + this.unstable.length = newLength; + } + Push(value: Object) labels Failed { assert(this.arrayIsPushable); if (this.hasDoubles) { @@ -1702,23 +2235,41 @@ struct FastJSArrayWitness { } } - stable: JSArray; + MoveElements(dst: intptr, src: intptr, length: intptr) { + assert(this.arrayIsPushable); + if (this.hasDoubles) { + let elements: FixedDoubleArray = + Cast<FixedDoubleArray>(this.unstable.elements) + otherwise unreachable; + TorqueMoveElements(elements, dst, src, length); + } else { + let elements: FixedArray = Cast<FixedArray>(this.unstable.elements) + otherwise unreachable; + if (this.hasSmis) { + TorqueMoveElementsSmi(elements, dst, src, length); + } else { + TorqueMoveElements(elements, dst, src, length); + } + } + } + + const stable: JSArray; unstable: FastJSArray; - map: Map; - hasDoubles: bool; - hasSmis: bool; + const map: Map; + const hasDoubles: bool; + const hasSmis: bool; arrayIsPushable: bool; } macro NewFastJSArrayWitness(array: FastJSArray): FastJSArrayWitness { let kind = array.map.elements_kind; return FastJSArrayWitness{ - array, - array, - array.map, - !IsElementsKindLessThanOrEqual(kind, HOLEY_ELEMENTS), - IsElementsKindLessThanOrEqual(kind, HOLEY_SMI_ELEMENTS), - false + stable: array, + unstable: array, + map: array.map, + hasDoubles: !IsElementsKindLessThanOrEqual(kind, HOLEY_ELEMENTS), + hasSmis: IsElementsKindLessThanOrEqual(kind, HOLEY_SMI_ELEMENTS), + arrayIsPushable: false }; } @@ -1729,6 +2280,8 @@ extern macro TransitionElementsKind( extern macro IsCallable(HeapObject): bool; extern macro IsConstructor(HeapObject): bool; extern macro IsJSArray(HeapObject): bool; +extern macro IsJSProxy(HeapObject): bool; +extern macro IsJSRegExp(HeapObject): bool; extern macro IsMap(HeapObject): bool; extern macro IsJSFunction(HeapObject): bool; extern macro IsJSObject(HeapObject): bool; @@ -1742,6 +2295,7 @@ extern macro IsDetachedBuffer(JSArrayBuffer): bool; extern macro IsHeapNumber(HeapObject): bool; extern macro IsFixedArray(HeapObject): bool; extern macro IsNumber(Object): bool; +extern macro IsNumberNormalized(Number): bool; extern macro IsJSArrayMap(Map): bool; extern macro IsExtensibleMap(Map): bool; extern macro IsCustomElementsReceiverInstanceType(int32): bool; @@ -1774,7 +2328,7 @@ macro ToBoolean(obj: Object): bool { } } -macro ToIndex(input: Object, context: Context): Number +transitioning macro ToIndex(input: Object, context: Context): Number labels RangeError { if (input == Undefined) { return 0; diff --git a/deps/v8/src/builtins/builtins-api.cc b/deps/v8/src/builtins/builtins-api.cc index e1c76c0fd9..ff77f32e4a 100644 --- a/deps/v8/src/builtins/builtins-api.cc +++ b/deps/v8/src/builtins/builtins-api.cc @@ -183,24 +183,10 @@ MaybeHandle<Object> Builtins::InvokeApiFunction(Isolate* isolate, } } - if (function->IsFunctionTemplateInfo()) { - Handle<FunctionTemplateInfo> info = - Handle<FunctionTemplateInfo>::cast(function); - // If we need to break at function entry, go the long way. Instantiate the - // function, use the DebugBreakTrampoline, and call it through JS. - if (info->BreakAtEntry()) { - DCHECK(!is_construct); - DCHECK(new_target->IsUndefined(isolate)); - Handle<JSFunction> function; - ASSIGN_RETURN_ON_EXCEPTION(isolate, function, - ApiNatives::InstantiateFunction( - info, MaybeHandle<v8::internal::Name>()), - Object); - Handle<Code> trampoline = BUILTIN_CODE(isolate, DebugBreakTrampoline); - function->set_code(*trampoline); - return Execution::Call(isolate, function, receiver, argc, args); - } - } + // We assume that all lazy accessor pairs have been instantiated when setting + // a break point on any API function. + DCHECK_IMPLIES(function->IsFunctionTemplateInfo(), + !Handle<FunctionTemplateInfo>::cast(function)->BreakAtEntry()); Handle<FunctionTemplateInfo> fun_data = function->IsFunctionTemplateInfo() diff --git a/deps/v8/src/builtins/builtins-array-gen.cc b/deps/v8/src/builtins/builtins-array-gen.cc index 7dfe705811..57f2f776ea 100644 --- a/deps/v8/src/builtins/builtins-array-gen.cc +++ b/deps/v8/src/builtins/builtins-array-gen.cc @@ -31,66 +31,6 @@ ArrayBuiltinsAssembler::ArrayBuiltinsAssembler( to_(this, MachineRepresentation::kTagged, SmiConstant(0)), fully_spec_compliant_(this, {&k_, &a_, &to_}) {} -void ArrayBuiltinsAssembler::FindResultGenerator() { - a_.Bind(UndefinedConstant()); -} - -Node* ArrayBuiltinsAssembler::FindProcessor(Node* k_value, Node* k) { - Node* value = CallJS(CodeFactory::Call(isolate()), context(), callbackfn(), - this_arg(), k_value, k, o()); - Label false_continue(this), return_true(this); - BranchIfToBooleanIsTrue(value, &return_true, &false_continue); - BIND(&return_true); - ReturnFromBuiltin(k_value); - BIND(&false_continue); - return a(); - } - - void ArrayBuiltinsAssembler::FindIndexResultGenerator() { - a_.Bind(SmiConstant(-1)); - } - - Node* ArrayBuiltinsAssembler::FindIndexProcessor(Node* k_value, Node* k) { - Node* value = CallJS(CodeFactory::Call(isolate()), context(), callbackfn(), - this_arg(), k_value, k, o()); - Label false_continue(this), return_true(this); - BranchIfToBooleanIsTrue(value, &return_true, &false_continue); - BIND(&return_true); - ReturnFromBuiltin(k); - BIND(&false_continue); - return a(); - } - - void ArrayBuiltinsAssembler::SomeResultGenerator() { - a_.Bind(FalseConstant()); - } - - Node* ArrayBuiltinsAssembler::SomeProcessor(Node* k_value, Node* k) { - Node* value = CallJS(CodeFactory::Call(isolate()), context(), callbackfn(), - this_arg(), k_value, k, o()); - Label false_continue(this), return_true(this); - BranchIfToBooleanIsTrue(value, &return_true, &false_continue); - BIND(&return_true); - ReturnFromBuiltin(TrueConstant()); - BIND(&false_continue); - return a(); - } - - void ArrayBuiltinsAssembler::EveryResultGenerator() { - a_.Bind(TrueConstant()); - } - - Node* ArrayBuiltinsAssembler::EveryProcessor(Node* k_value, Node* k) { - Node* value = CallJS(CodeFactory::Call(isolate()), context(), callbackfn(), - this_arg(), k_value, k, o()); - Label true_continue(this), return_false(this); - BranchIfToBooleanIsTrue(value, &true_continue, &return_false); - BIND(&return_false); - ReturnFromBuiltin(FalseConstant()); - BIND(&true_continue); - return a(); - } - void ArrayBuiltinsAssembler::TypedArrayMapResultGenerator() { // 6. Let A be ? TypedArraySpeciesCreate(O, len). TNode<JSTypedArray> original_array = CAST(o()); @@ -172,9 +112,10 @@ Node* ArrayBuiltinsAssembler::FindProcessor(Node* k_value, Node* k) { TNode<ExternalReference> memset = ExternalConstant(ExternalReference::libc_memset_function()); STATIC_ASSERT(kSizetSize == kIntptrSize); - CallCFunction3(MachineType::Pointer(), MachineType::Pointer(), - MachineType::IntPtr(), MachineType::UintPtr(), memset, - backing_store, IntPtrConstant(0), byte_length); + CallCFunction(memset, MachineType::Pointer(), + std::make_pair(MachineType::Pointer(), backing_store), + std::make_pair(MachineType::IntPtr(), IntPtrConstant(0)), + std::make_pair(MachineType::UintPtr(), byte_length)); } void ArrayBuiltinsAssembler::ReturnFromBuiltin(Node* value) { @@ -592,139 +533,6 @@ TF_BUILTIN(ArrayPrototypePush, CodeStubAssembler) { } } -TF_BUILTIN(ArrayPrototypeShift, CodeStubAssembler) { - TNode<Int32T> argc = - UncheckedCast<Int32T>(Parameter(Descriptor::kJSActualArgumentsCount)); - TNode<Context> context = CAST(Parameter(Descriptor::kContext)); - CSA_ASSERT(this, IsUndefined(Parameter(Descriptor::kJSNewTarget))); - - CodeStubArguments args(this, ChangeInt32ToIntPtr(argc)); - TNode<Object> receiver = args.GetReceiver(); - - Label runtime(this, Label::kDeferred); - Label fast(this); - - // Only shift in this stub if - // 1) the array has fast elements - // 2) the length is writable, - // 3) the elements backing store isn't copy-on-write, - // 4) we aren't supposed to shrink the backing store, - // 5) we aren't supposed to left-trim the backing store. - - // 1) Check that the array has fast elements. - BranchIfFastJSArray(receiver, context, &fast, &runtime); - - BIND(&fast); - { - TNode<JSArray> array_receiver = CAST(receiver); - CSA_ASSERT(this, TaggedIsPositiveSmi(LoadJSArrayLength(array_receiver))); - - // 2) Ensure that the length is writable. - // This check needs to happen before the check for length zero. - // The spec requires a "SetProperty(array, 'length', 0)" call when - // the length is zero. This must throw an exception in the case of a - // read-only length. - EnsureArrayLengthWritable(LoadMap(array_receiver), &runtime); - - TNode<IntPtrT> length = - LoadAndUntagObjectField(array_receiver, JSArray::kLengthOffset); - Label return_undefined(this), fast_elements_tagged(this), - fast_elements_smi(this); - GotoIf(IntPtrEqual(length, IntPtrConstant(0)), &return_undefined); - - // 3) Check that the elements backing store isn't copy-on-write. - TNode<FixedArrayBase> elements = LoadElements(array_receiver); - GotoIf(WordEqual(LoadMap(elements), LoadRoot(RootIndex::kFixedCOWArrayMap)), - &runtime); - - TNode<IntPtrT> new_length = IntPtrSub(length, IntPtrConstant(1)); - - // 4) Check that we're not supposed to right-trim the backing store, as - // implemented in elements.cc:ElementsAccessorBase::SetLengthImpl. - Node* capacity = SmiUntag(LoadFixedArrayBaseLength(elements)); - GotoIf(IntPtrLessThan( - IntPtrAdd(IntPtrAdd(new_length, new_length), - IntPtrConstant(JSObject::kMinAddedElementsCapacity)), - capacity), - &runtime); - - // 5) Check that we're not supposed to left-trim the backing store, as - // implemented in elements.cc:FastElementsAccessor::MoveElements. - GotoIf(IntPtrGreaterThan(new_length, - IntPtrConstant(JSArray::kMaxCopyElements)), - &runtime); - - StoreObjectFieldNoWriteBarrier(array_receiver, JSArray::kLengthOffset, - SmiTag(new_length)); - - TNode<IntPtrT> element_zero = IntPtrConstant(0); - TNode<IntPtrT> element_one = IntPtrConstant(1); - TNode<Int32T> elements_kind = LoadElementsKind(array_receiver); - GotoIf( - Int32LessThanOrEqual(elements_kind, Int32Constant(HOLEY_SMI_ELEMENTS)), - &fast_elements_smi); - GotoIf(Int32LessThanOrEqual(elements_kind, Int32Constant(HOLEY_ELEMENTS)), - &fast_elements_tagged); - - // Fast double elements kind: - { - CSA_ASSERT(this, - Int32LessThanOrEqual(elements_kind, - Int32Constant(HOLEY_DOUBLE_ELEMENTS))); - - VARIABLE(result, MachineRepresentation::kTagged, UndefinedConstant()); - - Label move_elements(this); - result.Bind(AllocateHeapNumberWithValue(LoadFixedDoubleArrayElement( - CAST(elements), element_zero, &move_elements))); - Goto(&move_elements); - BIND(&move_elements); - - MoveElements(HOLEY_DOUBLE_ELEMENTS, elements, element_zero, element_one, - new_length); - StoreFixedDoubleArrayHole(CAST(elements), new_length); - args.PopAndReturn(result.value()); - } - - BIND(&fast_elements_tagged); - { - TNode<FixedArray> elements_fixed_array = CAST(elements); - Node* value = LoadFixedArrayElement(elements_fixed_array, 0); - MoveElements(HOLEY_ELEMENTS, elements, element_zero, element_one, - new_length); - StoreFixedArrayElement(elements_fixed_array, new_length, - TheHoleConstant()); - GotoIf(WordEqual(value, TheHoleConstant()), &return_undefined); - args.PopAndReturn(value); - } - - BIND(&fast_elements_smi); - { - TNode<FixedArray> elements_fixed_array = CAST(elements); - Node* value = LoadFixedArrayElement(elements_fixed_array, 0); - MoveElements(HOLEY_SMI_ELEMENTS, elements, element_zero, element_one, - new_length); - StoreFixedArrayElement(elements_fixed_array, new_length, - TheHoleConstant()); - GotoIf(WordEqual(value, TheHoleConstant()), &return_undefined); - args.PopAndReturn(value); - } - - BIND(&return_undefined); - { args.PopAndReturn(UndefinedConstant()); } - } - - BIND(&runtime); - { - // 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::kArrayShift, context, target, UndefinedConstant(), - argc); - } -} - TF_BUILTIN(ExtractFastJSArray, ArrayBuiltinsAssembler) { ParameterMode mode = OptimalParameterMode(); TNode<Context> context = CAST(Parameter(Descriptor::kContext)); @@ -1047,81 +855,6 @@ TF_BUILTIN(ArrayFrom, ArrayPopulatorAssembler) { args.PopAndReturn(array.value()); } -// ES #sec-get-%typedarray%.prototype.find -TF_BUILTIN(TypedArrayPrototypeFind, ArrayBuiltinsAssembler) { - TNode<IntPtrT> argc = - ChangeInt32ToIntPtr(Parameter(Descriptor::kJSActualArgumentsCount)); - CodeStubArguments args(this, argc); - TNode<Context> context = CAST(Parameter(Descriptor::kContext)); - TNode<Object> receiver = args.GetReceiver(); - Node* callbackfn = args.GetOptionalArgumentValue(0); - Node* this_arg = args.GetOptionalArgumentValue(1); - - InitIteratingArrayBuiltinBody(context, receiver, callbackfn, this_arg, argc); - - GenerateIteratingTypedArrayBuiltinBody( - "%TypedArray%.prototype.find", - &ArrayBuiltinsAssembler::FindResultGenerator, - &ArrayBuiltinsAssembler::FindProcessor, - &ArrayBuiltinsAssembler::NullPostLoopAction); -} - -// ES #sec-get-%typedarray%.prototype.findIndex -TF_BUILTIN(TypedArrayPrototypeFindIndex, ArrayBuiltinsAssembler) { - TNode<IntPtrT> argc = - ChangeInt32ToIntPtr(Parameter(Descriptor::kJSActualArgumentsCount)); - CodeStubArguments args(this, argc); - TNode<Context> context = CAST(Parameter(Descriptor::kContext)); - TNode<Object> receiver = args.GetReceiver(); - Node* callbackfn = args.GetOptionalArgumentValue(0); - Node* this_arg = args.GetOptionalArgumentValue(1); - - InitIteratingArrayBuiltinBody(context, receiver, callbackfn, this_arg, argc); - - GenerateIteratingTypedArrayBuiltinBody( - "%TypedArray%.prototype.findIndex", - &ArrayBuiltinsAssembler::FindIndexResultGenerator, - &ArrayBuiltinsAssembler::FindIndexProcessor, - &ArrayBuiltinsAssembler::NullPostLoopAction); -} - - -TF_BUILTIN(TypedArrayPrototypeSome, ArrayBuiltinsAssembler) { - TNode<IntPtrT> argc = - ChangeInt32ToIntPtr(Parameter(Descriptor::kJSActualArgumentsCount)); - CodeStubArguments args(this, argc); - TNode<Context> context = CAST(Parameter(Descriptor::kContext)); - TNode<Object> receiver = args.GetReceiver(); - Node* callbackfn = args.GetOptionalArgumentValue(0); - Node* this_arg = args.GetOptionalArgumentValue(1); - - InitIteratingArrayBuiltinBody(context, receiver, callbackfn, this_arg, argc); - - GenerateIteratingTypedArrayBuiltinBody( - "%TypedArray%.prototype.some", - &ArrayBuiltinsAssembler::SomeResultGenerator, - &ArrayBuiltinsAssembler::SomeProcessor, - &ArrayBuiltinsAssembler::NullPostLoopAction); -} - -TF_BUILTIN(TypedArrayPrototypeEvery, ArrayBuiltinsAssembler) { - TNode<IntPtrT> argc = - ChangeInt32ToIntPtr(Parameter(Descriptor::kJSActualArgumentsCount)); - CodeStubArguments args(this, argc); - TNode<Context> context = CAST(Parameter(Descriptor::kContext)); - TNode<Object> receiver = args.GetReceiver(); - Node* callbackfn = args.GetOptionalArgumentValue(0); - Node* this_arg = args.GetOptionalArgumentValue(1); - - InitIteratingArrayBuiltinBody(context, receiver, callbackfn, this_arg, argc); - - GenerateIteratingTypedArrayBuiltinBody( - "%TypedArray%.prototype.every", - &ArrayBuiltinsAssembler::EveryResultGenerator, - &ArrayBuiltinsAssembler::EveryProcessor, - &ArrayBuiltinsAssembler::NullPostLoopAction); -} - TF_BUILTIN(TypedArrayPrototypeMap, ArrayBuiltinsAssembler) { TNode<IntPtrT> argc = ChangeInt32ToIntPtr(Parameter(Descriptor::kJSActualArgumentsCount)); diff --git a/deps/v8/src/builtins/builtins-array-gen.h b/deps/v8/src/builtins/builtins-array-gen.h index 8aa12b8858..8a9846fac2 100644 --- a/deps/v8/src/builtins/builtins-array-gen.h +++ b/deps/v8/src/builtins/builtins-array-gen.h @@ -72,13 +72,13 @@ class ArrayBuiltinsAssembler : public CodeStubAssembler { TNode<ExternalReference> isolate_ptr = ExternalConstant(ExternalReference::isolate_address(isolate())); return UncheckedCast<String>( - CallCFunction5(MachineType::AnyTagged(), // <return> String - MachineType::Pointer(), // Isolate* - MachineType::AnyTagged(), // FixedArray fixed_array - MachineType::IntPtr(), // intptr_t length - MachineType::AnyTagged(), // String sep - MachineType::AnyTagged(), // String dest - func, isolate_ptr, fixed_array, length, sep, dest)); + CallCFunction(func, + MachineType::AnyTagged(), // <return> String + std::make_pair(MachineType::Pointer(), isolate_ptr), + std::make_pair(MachineType::AnyTagged(), fixed_array), + std::make_pair(MachineType::IntPtr(), length), + std::make_pair(MachineType::AnyTagged(), sep), + std::make_pair(MachineType::AnyTagged(), dest))); } protected: diff --git a/deps/v8/src/builtins/builtins-array.cc b/deps/v8/src/builtins/builtins-array.cc index 8df340ece7..921b2c1f2f 100644 --- a/deps/v8/src/builtins/builtins-array.cc +++ b/deps/v8/src/builtins/builtins-array.cc @@ -817,6 +817,8 @@ uint32_t EstimateElementCount(Isolate* isolate, Handle<JSArray> array) { case PACKED_SMI_ELEMENTS: case HOLEY_SMI_ELEMENTS: case PACKED_ELEMENTS: + case PACKED_FROZEN_ELEMENTS: + case PACKED_SEALED_ELEMENTS: case HOLEY_ELEMENTS: { // Fast elements can't have lengths that are not representable by // a 32-bit signed integer. @@ -881,6 +883,8 @@ void CollectElementIndices(Isolate* isolate, Handle<JSObject> object, switch (kind) { case PACKED_SMI_ELEMENTS: case PACKED_ELEMENTS: + case PACKED_FROZEN_ELEMENTS: + case PACKED_SEALED_ELEMENTS: case HOLEY_SMI_ELEMENTS: case HOLEY_ELEMENTS: { DisallowHeapAllocation no_gc; @@ -1050,6 +1054,8 @@ bool IterateElements(Isolate* isolate, Handle<JSReceiver> receiver, switch (array->GetElementsKind()) { case PACKED_SMI_ELEMENTS: case PACKED_ELEMENTS: + case PACKED_FROZEN_ELEMENTS: + case PACKED_SEALED_ELEMENTS: case HOLEY_SMI_ELEMENTS: case HOLEY_ELEMENTS: { // Run through the elements FixedArray and use HasElement and GetElement @@ -1205,6 +1211,9 @@ Object Slow_ArrayConcat(BuiltinArguments* args, Handle<Object> species, if (length_estimate != 0) { ElementsKind array_kind = GetPackedElementsKind(array->GetElementsKind()); + if (IsPackedFrozenOrSealedElementsKind(array_kind)) { + array_kind = PACKED_ELEMENTS; + } kind = GetMoreGeneralElementsKind(kind, array_kind); } element_estimate = EstimateElementCount(isolate, array); @@ -1297,6 +1306,8 @@ Object Slow_ArrayConcat(BuiltinArguments* args, Handle<Object> species, } case HOLEY_ELEMENTS: case PACKED_ELEMENTS: + case PACKED_FROZEN_ELEMENTS: + case PACKED_SEALED_ELEMENTS: case DICTIONARY_ELEMENTS: case NO_ELEMENTS: DCHECK_EQ(0u, length); diff --git a/deps/v8/src/builtins/builtins-async-iterator-gen.cc b/deps/v8/src/builtins/builtins-async-iterator-gen.cc index 3672bda9d1..d4937c0e1f 100644 --- a/deps/v8/src/builtins/builtins-async-iterator-gen.cc +++ b/deps/v8/src/builtins/builtins-async-iterator-gen.cc @@ -36,13 +36,6 @@ class AsyncFromSyncBuiltinsAssembler : public AsyncBuiltinsAssembler { const char* operation_name, Label::Type reject_label_type = Label::kDeferred, Node* const initial_exception_value = nullptr); - void Generate_AsyncFromSyncIteratorMethodOptimized( - Node* const context, Node* const iterator, Node* const sent_value, - const SyncIteratorNodeGenerator& get_method, - const UndefinedMethodHandler& if_method_undefined, - const char* operation_name, - Label::Type reject_label_type = Label::kDeferred, - Node* const initial_exception_value = nullptr); void Generate_AsyncFromSyncIteratorMethod( Node* const context, Node* const iterator, Node* const sent_value, @@ -57,19 +50,6 @@ class AsyncFromSyncBuiltinsAssembler : public AsyncBuiltinsAssembler { context, iterator, sent_value, get_method, if_method_undefined, operation_name, reject_label_type, initial_exception_value); } - void Generate_AsyncFromSyncIteratorMethodOptimized( - Node* const context, Node* const iterator, Node* const sent_value, - Handle<String> name, const UndefinedMethodHandler& if_method_undefined, - const char* operation_name, - Label::Type reject_label_type = Label::kDeferred, - Node* const initial_exception_value = nullptr) { - auto get_method = [=](Node* const sync_iterator) { - return GetProperty(context, sync_iterator, name); - }; - return Generate_AsyncFromSyncIteratorMethodOptimized( - context, iterator, sent_value, get_method, if_method_undefined, - operation_name, reject_label_type, initial_exception_value); - } // Load "value" and "done" from an iterator result object. If an exception // is thrown at any point, jumps to te `if_exception` label with exception @@ -152,79 +132,16 @@ void AsyncFromSyncBuiltinsAssembler::Generate_AsyncFromSyncIteratorMethod( Node* done; std::tie(value, done) = LoadIteratorResult( context, native_context, iter_result, &reject_promise, &var_exception); - Node* const wrapper = AllocateAndInitJSPromise(context); - - // Perform ! Call(valueWrapperCapability.[[Resolve]], undefined, « - // throwValue »). - CallBuiltin(Builtins::kResolvePromise, context, wrapper, value); - - // Let onFulfilled be a new built-in function object as defined in - // Async Iterator Value Unwrap Functions. - // Set onFulfilled.[[Done]] to throwDone. - Node* const on_fulfilled = CreateUnwrapClosure(native_context, done); - - // Perform ! PerformPromiseThen(valueWrapperCapability.[[Promise]], - // onFulfilled, undefined, promiseCapability). - Return(CallBuiltin(Builtins::kPerformPromiseThen, context, wrapper, - on_fulfilled, UndefinedConstant(), promise)); - - BIND(&reject_promise); - { - Node* const exception = var_exception.value(); - CallBuiltin(Builtins::kRejectPromise, context, promise, exception, - TrueConstant()); - Return(promise); - } -} - -void AsyncFromSyncBuiltinsAssembler:: - Generate_AsyncFromSyncIteratorMethodOptimized( - Node* const context, Node* const iterator, Node* const sent_value, - const SyncIteratorNodeGenerator& get_method, - const UndefinedMethodHandler& if_method_undefined, - const char* operation_name, Label::Type reject_label_type, - Node* const initial_exception_value) { - Node* const native_context = LoadNativeContext(context); - Node* const promise = AllocateAndInitJSPromise(context); - - VARIABLE(var_exception, MachineRepresentation::kTagged, - initial_exception_value == nullptr ? UndefinedConstant() - : initial_exception_value); - Label reject_promise(this, reject_label_type); - - ThrowIfNotAsyncFromSyncIterator(context, iterator, &reject_promise, - &var_exception, operation_name); - - Node* const sync_iterator = - LoadObjectField(iterator, JSAsyncFromSyncIterator::kSyncIteratorOffset); - - Node* const method = get_method(sync_iterator); - - if (if_method_undefined) { - Label if_isnotundefined(this); - - GotoIfNot(IsUndefined(method), &if_isnotundefined); - if_method_undefined(native_context, promise, &reject_promise); - - BIND(&if_isnotundefined); - } - - Node* const iter_result = CallJS(CodeFactory::Call(isolate()), context, - method, sync_iterator, sent_value); - GotoIfException(iter_result, &reject_promise, &var_exception); - - Node* value; - Node* done; - std::tie(value, done) = LoadIteratorResult( - context, native_context, iter_result, &reject_promise, &var_exception); Node* const promise_fun = LoadContextElement(native_context, Context::PROMISE_FUNCTION_INDEX); CSA_ASSERT(this, IsConstructor(promise_fun)); - // Let valueWrapper be ? PromiseResolve(« value »). - Node* const valueWrapper = CallBuiltin(Builtins::kPromiseResolve, - native_context, promise_fun, value); + // Let valueWrapper be PromiseResolve(%Promise%, « value »). + Node* const value_wrapper = CallBuiltin(Builtins::kPromiseResolve, + native_context, promise_fun, value); + // IfAbruptRejectPromise(valueWrapper, promiseCapability). + GotoIfException(value_wrapper, &reject_promise, &var_exception); // Let onFulfilled be a new built-in function object as defined in // Async Iterator Value Unwrap Functions. @@ -233,7 +150,7 @@ void AsyncFromSyncBuiltinsAssembler:: // Perform ! PerformPromiseThen(valueWrapper, // onFulfilled, undefined, promiseCapability). - Return(CallBuiltin(Builtins::kPerformPromiseThen, context, valueWrapper, + Return(CallBuiltin(Builtins::kPerformPromiseThen, context, value_wrapper, on_fulfilled, UndefinedConstant(), promise)); BIND(&reject_promise); diff --git a/deps/v8/src/builtins/builtins-bigint.cc b/deps/v8/src/builtins/builtins-bigint.cc index c23660e116..5c8a7e4871 100644 --- a/deps/v8/src/builtins/builtins-bigint.cc +++ b/deps/v8/src/builtins/builtins-bigint.cc @@ -127,10 +127,17 @@ BUILTIN(BigIntPrototypeToLocaleString) { HandleScope scope(isolate); #ifdef V8_INTL_SUPPORT if (FLAG_harmony_intl_bigint) { + // 1. Let x be ? thisBigIntValue(this value). + Handle<BigInt> x; + ASSIGN_RETURN_FAILURE_ON_EXCEPTION( + isolate, x, + ThisBigIntValue(isolate, args.receiver(), + "BigInt.prototype.toLocaleString")); + RETURN_RESULT_OR_FAILURE( - isolate, Intl::NumberToLocaleString(isolate, args.receiver(), - args.atOrUndefined(isolate, 1), - args.atOrUndefined(isolate, 2))); + isolate, + Intl::NumberToLocaleString(isolate, x, args.atOrUndefined(isolate, 1), + args.atOrUndefined(isolate, 2))); } // Fallbacks to old toString implemention if flag is off or no // V8_INTL_SUPPORT diff --git a/deps/v8/src/builtins/builtins-call-gen.cc b/deps/v8/src/builtins/builtins-call-gen.cc index 2912c51136..51870cbc4e 100644 --- a/deps/v8/src/builtins/builtins-call-gen.cc +++ b/deps/v8/src/builtins/builtins-call-gen.cc @@ -498,30 +498,18 @@ void CallOrConstructBuiltinsAssembler::CallFunctionTemplate( CodeStubArguments args(this, argc); Label throw_illegal_invocation(this, Label::kDeferred); - // For API callbacks we need to call ToObject on the receiver. - // And in case the receiver is a JSObject already, we might - // need to perform access checks in the current {context}, - // depending on whether the "needs access check" bit is - // set on the receiver _and_ the {function_template_info} - // doesn't have the "accepts any receiver" bit set. - TVARIABLE(Object, var_receiver, args.GetReceiver()); - if (mode == CallFunctionTemplateMode::kCheckCompatibleReceiver) { - // We are only interested to see that receiver is compatible - // for the {function_template_info}, and don't need to bother - // doing any access checks. So ensure that the receiver is - // actually a JSReceiver. - var_receiver = ToObject_Inline(context, var_receiver.value()); - } else { - Label receiver_is_primitive(this, Label::kDeferred), - receiver_needs_access_check(this, &var_receiver, Label::kDeferred), + // For API callbacks the receiver is always a JSReceiver (since + // they are treated like sloppy mode functions). We might need + // to perform access checks in the current {context}, depending + // on whether the "needs access check" bit is set on the receiver + // _and_ the {function_template_info} doesn't have the "accepts + // any receiver" bit set. + TNode<JSReceiver> receiver = CAST(args.GetReceiver()); + if (mode == CallFunctionTemplateMode::kCheckAccess || + mode == CallFunctionTemplateMode::kCheckAccessAndCompatibleReceiver) { + TNode<Map> receiver_map = LoadMap(receiver); + Label receiver_needs_access_check(this, Label::kDeferred), receiver_done(this); - - // Check if the receiver needs to be converted, or if it's already - // a JSReceiver, see if the "needs access check" bit is set _and_ - // the {function_template_info} doesn't just accept any receiver. - GotoIf(TaggedIsSmi(var_receiver.value()), &receiver_is_primitive); - TNode<Map> receiver_map = LoadMap(CAST(var_receiver.value())); - GotoIfNot(IsJSReceiverMap(receiver_map), &receiver_is_primitive); GotoIfNot( IsSetWord32<Map::IsAccessCheckNeededBit>(LoadMapBitField(receiver_map)), &receiver_done); @@ -531,32 +519,14 @@ void CallOrConstructBuiltinsAssembler::CallFunctionTemplate( 1 << FunctionTemplateInfo::kAcceptAnyReceiver), &receiver_done, &receiver_needs_access_check); - BIND(&receiver_is_primitive); - { - // Convert primitives to wrapper objects as necessary. In case - // null or undefined were passed, we need to do the access check - // on the global proxy here. - var_receiver = ToObject(context, var_receiver.value()); - args.SetReceiver(var_receiver.value()); - GotoIfNot(IsSetWord32<Map::IsAccessCheckNeededBit>( - LoadMapBitField(LoadMap(CAST(var_receiver.value())))), - &receiver_done); - TNode<WordT> function_template_info_flags = LoadAndUntagObjectField( - function_template_info, FunctionTemplateInfo::kFlagOffset); - Branch(IsSetWord(function_template_info_flags, - 1 << FunctionTemplateInfo::kAcceptAnyReceiver), - &receiver_done, &receiver_needs_access_check); - } - BIND(&receiver_needs_access_check); { - CallRuntime(Runtime::kAccessCheck, context, var_receiver.value()); + CallRuntime(Runtime::kAccessCheck, context, receiver); Goto(&receiver_done); } BIND(&receiver_done); } - TNode<JSReceiver> receiver = CAST(var_receiver.value()); // Figure out the API holder for the {receiver} depending on the // {mode} and the signature on the {function_template_info}. diff --git a/deps/v8/src/builtins/builtins-collections-gen.cc b/deps/v8/src/builtins/builtins-collections-gen.cc index 6672569f19..19a6ae0729 100644 --- a/deps/v8/src/builtins/builtins-collections-gen.cc +++ b/deps/v8/src/builtins/builtins-collections-gen.cc @@ -12,6 +12,7 @@ #include "src/heap/heap-inl.h" #include "src/objects/hash-table-inl.h" #include "src/objects/js-collection.h" +#include "src/objects/ordered-hash-table.h" #include "torque-generated/builtins-base-from-dsl-gen.h" #include "torque-generated/builtins-collections-from-dsl-gen.h" @@ -759,8 +760,9 @@ Node* CollectionsBuiltinsAssembler::CallGetOrCreateHashRaw(Node* const key) { MachineType type_ptr = MachineType::Pointer(); MachineType type_tagged = MachineType::AnyTagged(); - Node* const result = CallCFunction2(type_tagged, type_ptr, type_tagged, - function_addr, isolate_ptr, key); + Node* const result = CallCFunction(function_addr, type_tagged, + std::make_pair(type_ptr, isolate_ptr), + std::make_pair(type_tagged, key)); return result; } @@ -774,8 +776,10 @@ Node* CollectionsBuiltinsAssembler::CallGetHashRaw(Node* const key) { MachineType type_ptr = MachineType::Pointer(); MachineType type_tagged = MachineType::AnyTagged(); - Node* const result = CallCFunction2(type_tagged, type_ptr, type_tagged, - function_addr, isolate_ptr, key); + Node* const result = CallCFunction(function_addr, type_tagged, + std::make_pair(type_ptr, isolate_ptr), + std::make_pair(type_tagged, key)); + return SmiUntag(result); } @@ -2341,7 +2345,8 @@ void WeakCollectionsBuiltinsAssembler::AddEntry( TNode<Object> key, TNode<Object> value, TNode<IntPtrT> number_of_elements) { // See EphemeronHashTable::AddEntry(). TNode<IntPtrT> value_index = ValueIndexFromKeyIndex(key_index); - UnsafeStoreFixedArrayElement(table, key_index, key); + UnsafeStoreFixedArrayElement(table, key_index, key, + UPDATE_EPHEMERON_KEY_WRITE_BARRIER); UnsafeStoreFixedArrayElement(table, value_index, value); // See HashTableBase::ElementAdded(). @@ -2389,8 +2394,9 @@ TNode<Smi> WeakCollectionsBuiltinsAssembler::CreateIdentityHash( MachineType type_ptr = MachineType::Pointer(); MachineType type_tagged = MachineType::AnyTagged(); - return CAST(CallCFunction2(type_tagged, type_ptr, type_tagged, function_addr, - isolate_ptr, key)); + return CAST(CallCFunction(function_addr, type_tagged, + std::make_pair(type_ptr, isolate_ptr), + std::make_pair(type_tagged, key))); } TNode<IntPtrT> WeakCollectionsBuiltinsAssembler::EntryMask( @@ -2611,7 +2617,7 @@ TF_BUILTIN(WeakMapGet, WeakCollectionsBuiltinsAssembler) { Return(UndefinedConstant()); } -TF_BUILTIN(WeakMapHas, WeakCollectionsBuiltinsAssembler) { +TF_BUILTIN(WeakMapPrototypeHas, WeakCollectionsBuiltinsAssembler) { Node* const receiver = Parameter(Descriptor::kReceiver); Node* const key = Parameter(Descriptor::kKey); Node* const context = Parameter(Descriptor::kContext); @@ -2775,7 +2781,7 @@ TF_BUILTIN(WeakSetPrototypeDelete, CodeStubAssembler) { CallBuiltin(Builtins::kWeakCollectionDelete, context, receiver, value)); } -TF_BUILTIN(WeakSetHas, WeakCollectionsBuiltinsAssembler) { +TF_BUILTIN(WeakSetPrototypeHas, WeakCollectionsBuiltinsAssembler) { Node* const receiver = Parameter(Descriptor::kReceiver); Node* const key = Parameter(Descriptor::kKey); Node* const context = Parameter(Descriptor::kContext); diff --git a/deps/v8/src/builtins/builtins-console.cc b/deps/v8/src/builtins/builtins-console.cc index 6b7db301d6..edfb0a45c7 100644 --- a/deps/v8/src/builtins/builtins-console.cc +++ b/deps/v8/src/builtins/builtins-console.cc @@ -145,7 +145,7 @@ BUILTIN(ConsoleContext) { Handle<JSObject> prototype = factory->NewJSObject(isolate->object_function()); JSFunction::SetPrototype(cons, prototype); - Handle<JSObject> context = factory->NewJSObject(cons, TENURED); + Handle<JSObject> context = factory->NewJSObject(cons, AllocationType::kOld); DCHECK(context->IsJSObject()); int id = isolate->last_console_context_id() + 1; isolate->set_last_console_context_id(id); diff --git a/deps/v8/src/builtins/builtins-constructor-gen.cc b/deps/v8/src/builtins/builtins-constructor-gen.cc index cb26b38c00..5de4eca89e 100644 --- a/deps/v8/src/builtins/builtins-constructor-gen.cc +++ b/deps/v8/src/builtins/builtins-constructor-gen.cc @@ -71,7 +71,6 @@ TF_BUILTIN(FastNewClosure, ConstructorBuiltinsAssembler) { Node* const feedback_cell_map = LoadMap(feedback_cell); Label no_closures(this), one_closure(this), cell_done(this); - GotoIf(IsNoFeedbackCellMap(feedback_cell_map), &cell_done); GotoIf(IsNoClosuresCellMap(feedback_cell_map), &no_closures); GotoIf(IsOneClosureCellMap(feedback_cell_map), &one_closure); CSA_ASSERT(this, IsManyClosuresCellMap(feedback_cell_map), diff --git a/deps/v8/src/builtins/builtins-date-gen.cc b/deps/v8/src/builtins/builtins-date-gen.cc index 82a2549b60..3a09f9f52d 100644 --- a/deps/v8/src/builtins/builtins-date-gen.cc +++ b/deps/v8/src/builtins/builtins-date-gen.cc @@ -53,9 +53,10 @@ void DateBuiltinsAssembler::Generate_DatePrototype_GetField(Node* context, Node* field_index_smi = SmiConstant(field_index); Node* function = ExternalConstant(ExternalReference::get_date_field_function()); - Node* result = CallCFunction2( - MachineType::AnyTagged(), MachineType::AnyTagged(), - MachineType::AnyTagged(), function, receiver, field_index_smi); + Node* result = CallCFunction( + function, MachineType::AnyTagged(), + std::make_pair(MachineType::AnyTagged(), receiver), + std::make_pair(MachineType::AnyTagged(), field_index_smi)); Return(result); } diff --git a/deps/v8/src/builtins/builtins-date.cc b/deps/v8/src/builtins/builtins-date.cc index ffbeab26a3..6701db28a3 100644 --- a/deps/v8/src/builtins/builtins-date.cc +++ b/deps/v8/src/builtins/builtins-date.cc @@ -172,17 +172,20 @@ DateBuffer ToDateString(double time_val, DateCache* date_cache, const char* local_timezone = date_cache->LocalTimezone(time_ms); switch (mode) { case kDateOnly: - return FormatDate("%s %s %02d %04d", kShortWeekDays[weekday], - kShortMonths[month], day, year); + return FormatDate((year < 0) ? "%s %s %02d %05d" : "%s %s %02d %04d", + kShortWeekDays[weekday], kShortMonths[month], day, + year); case kTimeOnly: return FormatDate("%02d:%02d:%02d GMT%c%02d%02d (%s)", hour, min, sec, (timezone_offset < 0) ? '-' : '+', timezone_hour, timezone_min, local_timezone); case kDateAndTime: - return FormatDate("%s %s %02d %04d %02d:%02d:%02d GMT%c%02d%02d (%s)", - kShortWeekDays[weekday], kShortMonths[month], day, year, - hour, min, sec, (timezone_offset < 0) ? '-' : '+', - timezone_hour, timezone_min, local_timezone); + return FormatDate( + (year < 0) ? "%s %s %02d %05d %02d:%02d:%02d GMT%c%02d%02d (%s)" + : "%s %s %02d %04d %02d:%02d:%02d GMT%c%02d%02d (%s)", + kShortWeekDays[weekday], kShortMonths[month], day, year, hour, min, + sec, (timezone_offset < 0) ? '-' : '+', timezone_hour, timezone_min, + local_timezone); } UNREACHABLE(); } @@ -914,7 +917,9 @@ BUILTIN(DatePrototypeToUTCString) { int year, month, day, weekday, hour, min, sec, ms; isolate->date_cache()->BreakDownTime(time_ms, &year, &month, &day, &weekday, &hour, &min, &sec, &ms); - SNPrintF(ArrayVector(buffer), "%s, %02d %s %04d %02d:%02d:%02d GMT", + SNPrintF(ArrayVector(buffer), + (year < 0) ? "%s, %02d %s %05d %02d:%02d:%02d GMT" + : "%s, %02d %s %04d %02d:%02d:%02d GMT", kShortWeekDays[weekday], day, kShortMonths[month], year, hour, min, sec); return *isolate->factory()->NewStringFromAsciiChecked(buffer); diff --git a/deps/v8/src/builtins/builtins-definitions.h b/deps/v8/src/builtins/builtins-definitions.h index b53e72a376..aea41b8635 100644 --- a/deps/v8/src/builtins/builtins-definitions.h +++ b/deps/v8/src/builtins/builtins-definitions.h @@ -36,6 +36,7 @@ namespace internal { #define BUILTIN_LIST_BASE(CPP, API, TFJ, TFC, TFS, TFH, ASM) \ /* GC write barrirer */ \ TFC(RecordWrite, RecordWrite) \ + TFC(EphemeronKeyBarrier, EphemeronKeyBarrier) \ \ /* Adaptors for CPP/API builtin */ \ TFC(AdaptorWithExitFrame, CppBuiltinAdaptor) \ @@ -113,7 +114,6 @@ namespace internal { TFS(StringIndexOf, kReceiver, kSearchString, kPosition) \ TFC(StringLessThan, Compare) \ TFC(StringLessThanOrEqual, Compare) \ - TFS(StringRepeat, kString, kCount) \ TFC(StringSubstring, StringSubstring) \ \ /* OrderedHashTable helpers */ \ @@ -172,8 +172,8 @@ namespace internal { API(HandleApiCallAsConstructor) \ \ /* Adapters for Turbofan into runtime */ \ - TFC(AllocateInNewSpace, Allocate) \ - TFC(AllocateInOldSpace, Allocate) \ + TFC(AllocateInYoungGeneration, Allocate) \ + TFC(AllocateInOldGeneration, Allocate) \ \ /* TurboFan support builtins */ \ TFS(CopyFastSmiOrObjectElements, kObject) \ @@ -209,7 +209,7 @@ namespace internal { TFC(Typeof, Typeof) \ TFC(GetSuperConstructor, Typeof) \ TFC(BigIntToI64, BigIntToI64) \ - TFC(I64ToBigInt, BigIntToWasmI64) \ + TFC(I64ToBigInt, I64ToBigInt) \ \ /* Type conversions continuations */ \ TFC(ToBooleanLazyDeoptContinuation, TypeConversionStackParameter) \ @@ -346,7 +346,6 @@ namespace internal { TFJ(ArrayPrototypePush, SharedFunctionInfo::kDontAdaptArgumentsSentinel) \ /* ES6 #sec-array.prototype.shift */ \ CPP(ArrayShift) \ - TFJ(ArrayPrototypeShift, SharedFunctionInfo::kDontAdaptArgumentsSentinel) \ /* ES6 #sec-array.prototype.unshift */ \ CPP(ArrayUnshift) \ /* Support for Array.from and other array-copying idioms */ \ @@ -859,6 +858,10 @@ namespace internal { TFJ(PromiseAllResolveElementClosure, 1, kReceiver, kValue) \ /* ES #sec-promise.race */ \ TFJ(PromiseRace, 1, kReceiver, kIterable) \ + /* ES #sec-promise.allsettled */ \ + TFJ(PromiseAllSettled, 1, kReceiver, kIterable) \ + TFJ(PromiseAllSettledResolveElementClosure, 1, kReceiver, kValue) \ + TFJ(PromiseAllSettledRejectElementClosure, 1, kReceiver, kValue) \ /* V8 Extras: v8.createPromise(parent) */ \ TFJ(PromiseInternalConstructor, 1, kReceiver, kParent) \ /* V8 Extras: v8.rejectPromise(promise, reason) */ \ @@ -867,9 +870,6 @@ namespace internal { TFJ(PromiseInternalResolve, 2, kReceiver, kPromise, kResolution) \ \ /* Proxy */ \ - TFJ(ProxyConstructor, 2, kReceiver, kTarget, kHandler) \ - TFJ(ProxyRevocable, 2, kReceiver, kTarget, kHandler) \ - TFJ(ProxyRevoke, 0, kReceiver) \ TFS(ProxyGetProperty, kProxy, kName, kReceiverValue, kOnNonExistent) \ TFS(ProxyHasProperty, kProxy, kName) \ TFS(ProxySetProperty, kProxy, kName, kValue, kReceiverValue) \ @@ -938,8 +938,6 @@ namespace internal { TFJ(RegExpPrototypeUnicodeGetter, 0, kReceiver) \ CPP(RegExpRightContextGetter) \ \ - /* ES #sec-regexp.prototype-@@replace */ \ - TFJ(RegExpPrototypeReplace, SharedFunctionInfo::kDontAdaptArgumentsSentinel) \ /* ES #sec-regexp.prototype-@@split */ \ TFJ(RegExpPrototypeSplit, SharedFunctionInfo::kDontAdaptArgumentsSentinel) \ /* RegExp helpers */ \ @@ -947,7 +945,6 @@ namespace internal { TFS(RegExpExecInternal, kRegExp, kString, kLastIndex, kMatchInfo) \ TFS(RegExpMatchFast, kReceiver, kPattern) \ TFS(RegExpPrototypeExecSlow, kReceiver, kString) \ - TFS(RegExpReplace, kRegExp, kString, kReplaceValue) \ TFS(RegExpSearchFast, kReceiver, kPattern) \ TFS(RegExpSplit, kRegExp, kString, kLimit) \ \ @@ -998,14 +995,6 @@ namespace internal { CPP(StringFromCodePoint) \ /* ES6 #sec-string.fromcharcode */ \ TFJ(StringFromCharCode, SharedFunctionInfo::kDontAdaptArgumentsSentinel) \ - /* ES6 #sec-string.prototype.anchor */ \ - TFJ(StringPrototypeAnchor, 1, kReceiver, kValue) \ - /* ES6 #sec-string.prototype.big */ \ - TFJ(StringPrototypeBig, 0, kReceiver) \ - /* ES6 #sec-string.prototype.blink */ \ - TFJ(StringPrototypeBlink, 0, kReceiver) \ - /* ES6 #sec-string.prototype.bold */ \ - TFJ(StringPrototypeBold, 0, kReceiver) \ /* ES6 #sec-string.prototype.charat */ \ TFJ(StringPrototypeCharAt, 1, kReceiver, kPosition) \ /* ES6 #sec-string.prototype.charcodeat */ \ @@ -1014,23 +1003,13 @@ namespace internal { TFJ(StringPrototypeCodePointAt, 1, kReceiver, kPosition) \ /* ES6 #sec-string.prototype.concat */ \ TFJ(StringPrototypeConcat, SharedFunctionInfo::kDontAdaptArgumentsSentinel) \ - /* ES6 #sec-string.prototype.fontcolor */ \ - TFJ(StringPrototypeFontcolor, 1, kReceiver, kValue) \ - /* ES6 #sec-string.prototype.fontsize */ \ - TFJ(StringPrototypeFontsize, 1, kReceiver, kValue) \ - /* ES6 #sec-string.prototype.fixed */ \ - TFJ(StringPrototypeFixed, 0, kReceiver) \ /* ES6 #sec-string.prototype.includes */ \ TFJ(StringPrototypeIncludes, \ SharedFunctionInfo::kDontAdaptArgumentsSentinel) \ /* ES6 #sec-string.prototype.indexof */ \ TFJ(StringPrototypeIndexOf, SharedFunctionInfo::kDontAdaptArgumentsSentinel) \ - /* ES6 #sec-string.prototype.italics */ \ - TFJ(StringPrototypeItalics, 0, kReceiver) \ /* ES6 #sec-string.prototype.lastindexof */ \ CPP(StringPrototypeLastIndexOf) \ - /* ES6 #sec-string.prototype.link */ \ - TFJ(StringPrototypeLink, 1, kReceiver, kValue) \ /* ES6 #sec-string.prototype.match */ \ TFJ(StringPrototypeMatch, 1, kReceiver, kRegexp) \ /* ES #sec-string.prototype.matchAll */ \ @@ -1042,29 +1021,19 @@ namespace internal { /* ES6 #sec-string.prototype.padStart */ \ TFJ(StringPrototypePadStart, \ SharedFunctionInfo::kDontAdaptArgumentsSentinel) \ - /* ES6 #sec-string.prototype.repeat */ \ - TFJ(StringPrototypeRepeat, 1, kReceiver, kCount) \ /* ES6 #sec-string.prototype.replace */ \ TFJ(StringPrototypeReplace, 2, kReceiver, kSearch, kReplace) \ /* ES6 #sec-string.prototype.search */ \ TFJ(StringPrototypeSearch, 1, kReceiver, kRegexp) \ /* ES6 #sec-string.prototype.slice */ \ TFJ(StringPrototypeSlice, SharedFunctionInfo::kDontAdaptArgumentsSentinel) \ - /* ES6 #sec-string.prototype.small */ \ - TFJ(StringPrototypeSmall, 0, kReceiver) \ /* ES6 #sec-string.prototype.split */ \ TFJ(StringPrototypeSplit, SharedFunctionInfo::kDontAdaptArgumentsSentinel) \ - /* ES6 #sec-string.prototype.strike */ \ - TFJ(StringPrototypeStrike, 0, kReceiver) \ - /* ES6 #sec-string.prototype.sub */ \ - TFJ(StringPrototypeSub, 0, kReceiver) \ /* ES6 #sec-string.prototype.substr */ \ TFJ(StringPrototypeSubstr, SharedFunctionInfo::kDontAdaptArgumentsSentinel) \ /* ES6 #sec-string.prototype.substring */ \ TFJ(StringPrototypeSubstring, \ SharedFunctionInfo::kDontAdaptArgumentsSentinel) \ - /* ES6 #sec-string.prototype.sup */ \ - TFJ(StringPrototypeSup, 0, kReceiver) \ /* ES6 #sec-string.prototype.tostring */ \ TFJ(StringPrototypeToString, 0, kReceiver) \ TFJ(StringPrototypeTrim, SharedFunctionInfo::kDontAdaptArgumentsSentinel) \ @@ -1121,12 +1090,6 @@ namespace internal { CPP(TypedArrayPrototypeCopyWithin) \ /* ES6 #sec-%typedarray%.prototype.fill */ \ CPP(TypedArrayPrototypeFill) \ - /* ES6 %TypedArray%.prototype.find */ \ - TFJ(TypedArrayPrototypeFind, \ - SharedFunctionInfo::kDontAdaptArgumentsSentinel) \ - /* ES6 %TypedArray%.prototype.findIndex */ \ - TFJ(TypedArrayPrototypeFindIndex, \ - SharedFunctionInfo::kDontAdaptArgumentsSentinel) \ /* ES7 #sec-%typedarray%.prototype.includes */ \ CPP(TypedArrayPrototypeIncludes) \ /* ES6 #sec-%typedarray%.prototype.indexof */ \ @@ -1139,12 +1102,6 @@ namespace internal { TFJ(TypedArrayPrototypeSet, SharedFunctionInfo::kDontAdaptArgumentsSentinel) \ /* ES6 #sec-get-%typedarray%.prototype-@@tostringtag */ \ TFJ(TypedArrayPrototypeToStringTag, 0, kReceiver) \ - /* ES6 %TypedArray%.prototype.every */ \ - TFJ(TypedArrayPrototypeEvery, \ - SharedFunctionInfo::kDontAdaptArgumentsSentinel) \ - /* ES6 %TypedArray%.prototype.some */ \ - TFJ(TypedArrayPrototypeSome, \ - SharedFunctionInfo::kDontAdaptArgumentsSentinel) \ /* ES6 %TypedArray%.prototype.map */ \ TFJ(TypedArrayPrototypeMap, SharedFunctionInfo::kDontAdaptArgumentsSentinel) \ /* ES6 %TypedArray%.of */ \ @@ -1155,11 +1112,13 @@ namespace internal { /* Wasm */ \ ASM(WasmCompileLazy, Dummy) \ TFC(WasmAllocateHeapNumber, AllocateHeapNumber) \ - TFC(WasmAtomicWake, WasmAtomicWake) \ + TFC(WasmAtomicNotify, WasmAtomicNotify) \ TFC(WasmI32AtomicWait, WasmI32AtomicWait) \ TFC(WasmI64AtomicWait, WasmI64AtomicWait) \ TFC(WasmCallJavaScript, CallTrampoline) \ TFC(WasmMemoryGrow, WasmMemoryGrow) \ + TFC(WasmTableGet, WasmTableGet) \ + TFC(WasmTableSet, WasmTableSet) \ TFC(WasmRecordWrite, RecordWrite) \ TFC(WasmStackGuard, NoContext) \ TFC(WasmStackOverflow, NoContext) \ @@ -1177,20 +1136,20 @@ namespace internal { TFS(ThrowWasmTrapDataSegmentDropped) \ TFS(ThrowWasmTrapElemSegmentDropped) \ TFS(ThrowWasmTrapTableOutOfBounds) \ - TFC(BigIntToWasmI64, BigIntToWasmI64) \ + TFC(WasmI64ToBigInt, I64ToBigInt) \ TFC(WasmBigIntToI64, BigIntToI64) \ \ /* WeakMap */ \ TFJ(WeakMapConstructor, SharedFunctionInfo::kDontAdaptArgumentsSentinel) \ TFS(WeakMapLookupHashIndex, kTable, kKey) \ TFJ(WeakMapGet, 1, kReceiver, kKey) \ - TFJ(WeakMapHas, 1, kReceiver, kKey) \ + TFJ(WeakMapPrototypeHas, 1, kReceiver, kKey) \ TFJ(WeakMapPrototypeSet, 2, kReceiver, kKey, kValue) \ TFJ(WeakMapPrototypeDelete, 1, kReceiver, kKey) \ \ /* WeakSet */ \ TFJ(WeakSetConstructor, SharedFunctionInfo::kDontAdaptArgumentsSentinel) \ - TFJ(WeakSetHas, 1, kReceiver, kKey) \ + TFJ(WeakSetPrototypeHas, 1, kReceiver, kKey) \ TFJ(WeakSetPrototypeAdd, 1, kReceiver, kValue) \ TFJ(WeakSetPrototypeDelete, 1, kReceiver, kValue) \ \ @@ -1311,6 +1270,10 @@ namespace internal { CPP(DateTimeFormatInternalFormat) \ /* ecma402 #sec-intl.datetimeformat.prototype.format */ \ CPP(DateTimeFormatPrototypeFormat) \ + /* ecma402 #sec-intl.datetimeformat.prototype.formatrange */ \ + CPP(DateTimeFormatPrototypeFormatRange) \ + /* ecma402 #sec-intl.datetimeformat.prototype.formatrangetoparts */ \ + CPP(DateTimeFormatPrototypeFormatRangeToParts) \ /* ecma402 #sec-intl.datetimeformat.prototype.formattoparts */ \ CPP(DateTimeFormatPrototypeFormatToParts) \ /* ecma402 #sec-intl.datetimeformat.prototype.resolvedoptions */ \ @@ -1461,19 +1424,22 @@ namespace internal { // elements of the list coincide with {compiler::TrapId}, order matters. #define WASM_RUNTIME_STUB_LIST(V, VTRAP) \ FOREACH_WASM_TRAPREASON(VTRAP) \ + V(WasmCompileLazy) \ V(WasmAllocateHeapNumber) \ - V(WasmAtomicWake) \ + V(WasmAtomicNotify) \ V(WasmI32AtomicWait) \ V(WasmI64AtomicWait) \ V(WasmCallJavaScript) \ V(WasmMemoryGrow) \ + V(WasmTableGet) \ + V(WasmTableSet) \ V(WasmRecordWrite) \ V(WasmStackGuard) \ V(WasmStackOverflow) \ V(WasmToNumber) \ V(WasmThrow) \ V(DoubleToI) \ - V(BigIntToWasmI64) \ + V(WasmI64ToBigInt) \ V(WasmBigIntToI64) // The exception thrown in the following builtins are caught internally and will diff --git a/deps/v8/src/builtins/builtins-function.cc b/deps/v8/src/builtins/builtins-function.cc index cd68b261cc..900ef9fd3b 100644 --- a/deps/v8/src/builtins/builtins-function.cc +++ b/deps/v8/src/builtins/builtins-function.cc @@ -114,7 +114,7 @@ MaybeHandle<Object> CreateDynamicFunction(Isolate* isolate, Handle<Context> context(function->context(), isolate); function = isolate->factory()->NewFunctionFromSharedFunctionInfo( - map, shared_info, context, NOT_TENURED); + map, shared_info, context, AllocationType::kYoung); } return function; } @@ -150,7 +150,7 @@ BUILTIN(AsyncFunctionConstructor) { Handle<JSFunction> func = Handle<JSFunction>::cast(maybe_func); Handle<Script> script = handle(Script::cast(func->shared()->script()), isolate); - int position = script->GetEvalPosition(); + int position = Script::GetEvalPosition(isolate, script); USE(position); return *func; @@ -169,7 +169,7 @@ BUILTIN(AsyncGeneratorFunctionConstructor) { Handle<JSFunction> func = Handle<JSFunction>::cast(maybe_func); Handle<Script> script = handle(Script::cast(func->shared()->script()), isolate); - int position = script->GetEvalPosition(); + int position = Script::GetEvalPosition(isolate, script); USE(position); return *func; diff --git a/deps/v8/src/builtins/builtins-handler-gen.cc b/deps/v8/src/builtins/builtins-handler-gen.cc index 00602203b3..a722a6180b 100644 --- a/deps/v8/src/builtins/builtins-handler-gen.cc +++ b/deps/v8/src/builtins/builtins-handler-gen.cc @@ -262,6 +262,7 @@ TF_BUILTIN(ElementsTransitionAndStore_NoTransitionHandleCOW, V(PACKED_SMI_ELEMENTS) \ V(HOLEY_SMI_ELEMENTS) \ V(PACKED_ELEMENTS) \ + V(PACKED_SEALED_ELEMENTS) \ V(HOLEY_ELEMENTS) \ V(PACKED_DOUBLE_ELEMENTS) \ V(HOLEY_DOUBLE_ELEMENTS) \ diff --git a/deps/v8/src/builtins/builtins-internal-gen.cc b/deps/v8/src/builtins/builtins-internal-gen.cc index 312ca63e41..1b4805ef19 100644 --- a/deps/v8/src/builtins/builtins-internal-gen.cc +++ b/deps/v8/src/builtins/builtins-internal-gen.cc @@ -6,6 +6,7 @@ #include "src/builtins/builtins-utils-gen.h" #include "src/builtins/builtins.h" #include "src/code-stub-assembler.h" +#include "src/counters.h" #include "src/heap/heap-inl.h" // crbug.com/v8/8499 #include "src/ic/accessor-assembler.h" #include "src/ic/keyed-store-generic.h" @@ -281,15 +282,17 @@ class RecordWriteCodeStubAssembler : public CodeStubAssembler { Branch(ShouldSkipFPRegs(mode), &dont_save_fp, &save_fp); BIND(&dont_save_fp); { - CallCFunction1WithCallerSavedRegisters(return_type, arg0_type, function, - arg0, kDontSaveFPRegs); + CallCFunctionWithCallerSavedRegisters(function, return_type, + kDontSaveFPRegs, + std::make_pair(arg0_type, arg0)); Goto(next); } BIND(&save_fp); { - CallCFunction1WithCallerSavedRegisters(return_type, arg0_type, function, - arg0, kSaveFPRegs); + CallCFunctionWithCallerSavedRegisters(function, return_type, + kSaveFPRegs, + std::make_pair(arg0_type, arg0)); Goto(next); } } @@ -302,17 +305,18 @@ class RecordWriteCodeStubAssembler : public CodeStubAssembler { Branch(ShouldSkipFPRegs(mode), &dont_save_fp, &save_fp); BIND(&dont_save_fp); { - CallCFunction3WithCallerSavedRegisters(return_type, arg0_type, arg1_type, - arg2_type, function, arg0, arg1, - arg2, kDontSaveFPRegs); + CallCFunctionWithCallerSavedRegisters( + function, return_type, kDontSaveFPRegs, + std::make_pair(arg0_type, arg0), std::make_pair(arg1_type, arg1), + std::make_pair(arg2_type, arg2)); Goto(next); } BIND(&save_fp); { - CallCFunction3WithCallerSavedRegisters(return_type, arg0_type, arg1_type, - arg2_type, function, arg0, arg1, - arg2, kSaveFPRegs); + CallCFunctionWithCallerSavedRegisters( + function, return_type, kSaveFPRegs, std::make_pair(arg0_type, arg0), + std::make_pair(arg1_type, arg1), std::make_pair(arg2_type, arg2)); Goto(next); } } @@ -446,6 +450,27 @@ TF_BUILTIN(RecordWrite, RecordWriteCodeStubAssembler) { } BIND(&exit); + IncrementCounter(isolate()->counters()->write_barriers(), 1); + Return(TrueConstant()); +} + +TF_BUILTIN(EphemeronKeyBarrier, RecordWriteCodeStubAssembler) { + Label exit(this); + + Node* function = ExternalConstant( + ExternalReference::ephemeron_key_write_barrier_function()); + Node* isolate_constant = + ExternalConstant(ExternalReference::isolate_address(isolate())); + Node* address = Parameter(Descriptor::kSlotAddress); + Node* object = BitcastTaggedToWord(Parameter(Descriptor::kObject)); + Node* fp_mode = Parameter(Descriptor::kFPMode); + CallCFunction3WithCallerSavedRegistersMode( + MachineType::Int32(), MachineType::Pointer(), MachineType::Pointer(), + MachineType::Pointer(), function, object, address, isolate_constant, + fp_mode, &exit); + + BIND(&exit); + IncrementCounter(isolate()->counters()->write_barriers(), 1); Return(TrueConstant()); } @@ -680,21 +705,20 @@ TF_BUILTIN(AdaptorWithBuiltinExitFrame, InternalBuiltinsAssembler) { GenerateAdaptorWithExitFrameType<Descriptor>(Builtins::BUILTIN_EXIT); } -TF_BUILTIN(AllocateInNewSpace, CodeStubAssembler) { +TF_BUILTIN(AllocateInYoungGeneration, CodeStubAssembler) { TNode<IntPtrT> requested_size = UncheckedCast<IntPtrT>(Parameter(Descriptor::kRequestedSize)); - TailCallRuntime(Runtime::kAllocateInNewSpace, NoContextConstant(), + TailCallRuntime(Runtime::kAllocateInYoungGeneration, NoContextConstant(), SmiFromIntPtr(requested_size)); } -TF_BUILTIN(AllocateInOldSpace, CodeStubAssembler) { +TF_BUILTIN(AllocateInOldGeneration, CodeStubAssembler) { TNode<IntPtrT> requested_size = UncheckedCast<IntPtrT>(Parameter(Descriptor::kRequestedSize)); - int flags = AllocateTargetSpace::encode(OLD_SPACE); - TailCallRuntime(Runtime::kAllocateInTargetSpace, NoContextConstant(), - SmiFromIntPtr(requested_size), SmiConstant(flags)); + TailCallRuntime(Runtime::kAllocateInOldGeneration, NoContextConstant(), + SmiFromIntPtr(requested_size), SmiConstant(0)); } TF_BUILTIN(Abort, CodeStubAssembler) { diff --git a/deps/v8/src/builtins/builtins-intl-gen.cc b/deps/v8/src/builtins/builtins-intl-gen.cc index c0d469cfe3..9a95bb33c2 100644 --- a/deps/v8/src/builtins/builtins-intl-gen.cc +++ b/deps/v8/src/builtins/builtins-intl-gen.cc @@ -113,8 +113,9 @@ TF_BUILTIN(StringToLowerCaseIntl, IntlBuiltinsAssembler) { MachineType type_tagged = MachineType::AnyTagged(); - Node* const result = CallCFunction2(type_tagged, type_tagged, type_tagged, - function_addr, src, dst); + Node* const result = CallCFunction(function_addr, type_tagged, + std::make_pair(type_tagged, src), + std::make_pair(type_tagged, dst)); Return(result); } @@ -131,10 +132,10 @@ TF_BUILTIN(StringToLowerCaseIntl, IntlBuiltinsAssembler) { } TF_BUILTIN(StringPrototypeToLowerCaseIntl, IntlBuiltinsAssembler) { - Node* const maybe_string = Parameter(Descriptor::kReceiver); - Node* const context = Parameter(Descriptor::kContext); + TNode<Object> maybe_string = CAST(Parameter(Descriptor::kReceiver)); + TNode<Context> context = CAST(Parameter(Descriptor::kContext)); - Node* const string = + TNode<String> string = ToThisString(context, maybe_string, "String.prototype.toLowerCase"); Return(CallBuiltin(Builtins::kStringToLowerCaseIntl, context, string)); diff --git a/deps/v8/src/builtins/builtins-intl.cc b/deps/v8/src/builtins/builtins-intl.cc index 47054037e5..a5ef6a3c7c 100644 --- a/deps/v8/src/builtins/builtins-intl.cc +++ b/deps/v8/src/builtins/builtins-intl.cc @@ -157,6 +157,72 @@ BUILTIN(DateTimeFormatPrototypeFormatToParts) { isolate, JSDateTimeFormat::FormatToParts(isolate, dtf, date_value)); } +// Common code for DateTimeFormatPrototypeFormtRange(|ToParts) +template <class T> +V8_WARN_UNUSED_RESULT Object DateTimeFormatRange( + BuiltinArguments args, Isolate* isolate, const char* const method, + MaybeHandle<T> (*format)(Isolate*, Handle<JSDateTimeFormat>, double, + double)) { + // 1. Let dtf be this value. + // 2. If Type(dtf) is not Object, throw a TypeError exception. + CHECK_RECEIVER(JSObject, date_format_holder, method); + + Factory* factory = isolate->factory(); + + // 3. If dtf does not have an [[InitializedDateTimeFormat]] internal slot, + // throw a TypeError exception. + if (!date_format_holder->IsJSDateTimeFormat()) { + THROW_NEW_ERROR_RETURN_FAILURE( + isolate, NewTypeError(MessageTemplate::kIncompatibleMethodReceiver, + factory->NewStringFromAsciiChecked(method), + date_format_holder)); + } + Handle<JSDateTimeFormat> dtf = + Handle<JSDateTimeFormat>::cast(date_format_holder); + + // 4. If startDate is undefined or endDate is undefined, throw a RangeError + // exception. + Handle<Object> start_date = args.atOrUndefined(isolate, 1); + Handle<Object> end_date = args.atOrUndefined(isolate, 2); + if (start_date->IsUndefined(isolate) || end_date->IsUndefined(isolate)) { + THROW_NEW_ERROR_RETURN_FAILURE( + isolate, NewRangeError(MessageTemplate::kInvalidTimeValue)); + } + // 5. Let x be ? ToNumber(startDate). + ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, start_date, + Object::ToNumber(isolate, start_date)); + double x = start_date->Number(); + + // 6. Let y be ? ToNumber(endDate). + ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, end_date, + Object::ToNumber(isolate, end_date)); + double y = end_date->Number(); + // 7. If x is greater than y, throw a RangeError exception. + if (x > y) { + THROW_NEW_ERROR_RETURN_FAILURE( + isolate, NewRangeError(MessageTemplate::kInvalidTimeValue)); + } + + // 8. Return ? FormatDateTimeRange(dtf, x, y) + // OR + // 8. Return ? FormatDateTimeRangeToParts(dtf, x, y). + RETURN_RESULT_OR_FAILURE(isolate, format(isolate, dtf, x, y)); +} + +BUILTIN(DateTimeFormatPrototypeFormatRange) { + const char* const method = "Intl.DateTimeFormat.prototype.formatRange"; + HandleScope handle_scope(isolate); + return DateTimeFormatRange<String>(args, isolate, method, + JSDateTimeFormat::FormatRange); +} + +BUILTIN(DateTimeFormatPrototypeFormatRangeToParts) { + const char* const method = "Intl.DateTimeFormat.prototype.formatRangeToParts"; + HandleScope handle_scope(isolate); + return DateTimeFormatRange<JSArray>(args, isolate, method, + JSDateTimeFormat::FormatRangeToParts); +} + namespace { Handle<JSFunction> CreateBoundFunction(Isolate* isolate, Handle<JSObject> object, @@ -639,7 +705,7 @@ BUILTIN(RelativeTimeFormatPrototypeFormat) { RETURN_RESULT_OR_FAILURE( isolate, JSRelativeTimeFormat::Format(isolate, value_obj, unit_obj, - format_holder, "format", false)); + format_holder)); } BUILTIN(RelativeTimeFormatPrototypeFormatToParts) { @@ -652,9 +718,9 @@ BUILTIN(RelativeTimeFormatPrototypeFormatToParts) { "Intl.RelativeTimeFormat.prototype.formatToParts"); Handle<Object> value_obj = args.atOrUndefined(isolate, 1); Handle<Object> unit_obj = args.atOrUndefined(isolate, 2); - RETURN_RESULT_OR_FAILURE(isolate, JSRelativeTimeFormat::Format( - isolate, value_obj, unit_obj, - format_holder, "formatToParts", true)); + RETURN_RESULT_OR_FAILURE( + isolate, JSRelativeTimeFormat::FormatToParts(isolate, value_obj, unit_obj, + format_holder)); } // Locale getters. diff --git a/deps/v8/src/builtins/builtins-lazy-gen.cc b/deps/v8/src/builtins/builtins-lazy-gen.cc index dae32f2d52..c1715542fc 100644 --- a/deps/v8/src/builtins/builtins-lazy-gen.cc +++ b/deps/v8/src/builtins/builtins-lazy-gen.cc @@ -127,13 +127,24 @@ void LazyBuiltinsAssembler::CompileLazy(TNode<JSFunction> function) { CAST(LoadObjectField(function, JSFunction::kSharedFunctionInfoOffset)); TNode<Code> sfi_code = GetSharedFunctionInfoCode(shared, &compile_function); - // Compile function if we don't have a valid feedback vector. - TNode<FeedbackVector> feedback_vector = - LoadFeedbackVector(function, &compile_function); + TNode<HeapObject> feedback_cell_value = LoadFeedbackCellValue(function); + + // If feedback cell isn't initialized, compile function + GotoIf(IsUndefined(feedback_cell_value), &compile_function); + + Label use_sfi_code(this); + // If there is no feedback, don't check for optimized code. + GotoIf(HasInstanceType(feedback_cell_value, CLOSURE_FEEDBACK_CELL_ARRAY_TYPE), + &use_sfi_code); + + // If it isn't undefined or fixed array it must be a feedback vector. + CSA_ASSERT(this, IsFeedbackVector(feedback_cell_value)); // Is there an optimization marker or optimized code in the feedback vector? - MaybeTailCallOptimizedCodeSlot(function, feedback_vector); + MaybeTailCallOptimizedCodeSlot(function, CAST(feedback_cell_value)); + Goto(&use_sfi_code); + BIND(&use_sfi_code); // If not, install the SFI's code entry and jump to that. CSA_ASSERT(this, WordNotEqual(sfi_code, HeapConstant(BUILTIN_CODE( isolate(), CompileLazy)))); diff --git a/deps/v8/src/builtins/builtins-math-gen.cc b/deps/v8/src/builtins/builtins-math-gen.cc index 36b0d30939..16d1e7d234 100644 --- a/deps/v8/src/builtins/builtins-math-gen.cc +++ b/deps/v8/src/builtins/builtins-math-gen.cc @@ -420,9 +420,9 @@ TF_BUILTIN(MathRandom, CodeStubAssembler) { MachineType type_tagged = MachineType::AnyTagged(); MachineType type_ptr = MachineType::Pointer(); - smi_index = - CAST(CallCFunction2(type_tagged, type_ptr, type_tagged, - refill_math_random, isolate_ptr, native_context)); + smi_index = CAST(CallCFunction(refill_math_random, type_tagged, + std::make_pair(type_ptr, isolate_ptr), + std::make_pair(type_tagged, native_context))); Goto(&if_cached); // Compute next index by decrement. diff --git a/deps/v8/src/builtins/builtins-microtask-queue-gen.cc b/deps/v8/src/builtins/builtins-microtask-queue-gen.cc index 2c1b748d0f..08c5a96193 100644 --- a/deps/v8/src/builtins/builtins-microtask-queue-gen.cc +++ b/deps/v8/src/builtins/builtins-microtask-queue-gen.cc @@ -409,9 +409,10 @@ void MicrotaskQueueBuiltinsAssembler::EnterMicrotaskContext( { Node* function = ExternalConstant(ExternalReference::call_enter_context_function()); - CallCFunction2(MachineType::Int32(), MachineType::Pointer(), - MachineType::Pointer(), function, hsi, - BitcastTaggedToWord(native_context)); + CallCFunction(function, MachineType::Int32(), + std::make_pair(MachineType::Pointer(), hsi), + std::make_pair(MachineType::Pointer(), + BitcastTaggedToWord(native_context))); Goto(&done); } @@ -509,9 +510,10 @@ TF_BUILTIN(EnqueueMicrotask, MicrotaskQueueBuiltinsAssembler) { ExternalConstant(ExternalReference::isolate_address(isolate())); Node* function = ExternalConstant(ExternalReference::call_enqueue_microtask_function()); - CallCFunction3(MachineType::AnyTagged(), MachineType::Pointer(), - MachineType::IntPtr(), MachineType::AnyTagged(), function, - isolate_constant, microtask_queue, microtask); + CallCFunction(function, MachineType::AnyTagged(), + std::make_pair(MachineType::Pointer(), isolate_constant), + std::make_pair(MachineType::IntPtr(), microtask_queue), + std::make_pair(MachineType::AnyTagged(), microtask)); Return(UndefinedConstant()); } diff --git a/deps/v8/src/builtins/builtins-promise-gen.cc b/deps/v8/src/builtins/builtins-promise-gen.cc index 22ffc2a851..513a595822 100644 --- a/deps/v8/src/builtins/builtins-promise-gen.cc +++ b/deps/v8/src/builtins/builtins-promise-gen.cc @@ -288,8 +288,9 @@ Node* PromiseBuiltinsAssembler::CreatePromiseAllResolveElementContext( return context; } -Node* PromiseBuiltinsAssembler::CreatePromiseAllResolveElementFunction( - Node* context, TNode<Smi> index, Node* native_context) { +TNode<JSFunction> +PromiseBuiltinsAssembler::CreatePromiseAllResolveElementFunction( + Node* context, TNode<Smi> index, Node* native_context, int slot_index) { CSA_ASSERT(this, SmiGreaterThan(index, SmiConstant(0))); CSA_ASSERT(this, SmiLessThanOrEqual( index, SmiConstant(PropertyArray::HashField::kMax))); @@ -297,10 +298,9 @@ Node* PromiseBuiltinsAssembler::CreatePromiseAllResolveElementFunction( Node* const map = LoadContextElement( native_context, Context::STRICT_FUNCTION_WITHOUT_PROTOTYPE_MAP_INDEX); - Node* const resolve_info = LoadContextElement( - native_context, Context::PROMISE_ALL_RESOLVE_ELEMENT_SHARED_FUN); - Node* const resolve = - AllocateFunctionWithMapAndContext(map, resolve_info, context); + Node* const resolve_info = LoadContextElement(native_context, slot_index); + TNode<JSFunction> resolve = + Cast(AllocateFunctionWithMapAndContext(map, resolve_info, context)); STATIC_ASSERT(PropertyArray::kNoHashSentinel == 0); StoreObjectFieldNoWriteBarrier(resolve, JSFunction::kPropertiesOrHashOffset, @@ -417,6 +417,8 @@ void PromiseBuiltinsAssembler::PerformPromiseThen( { VARIABLE(var_map, MachineRepresentation::kTagged); VARIABLE(var_handler, MachineRepresentation::kTagged); + VARIABLE(var_handler_context, MachineRepresentation::kTagged, + UndefinedConstant()); Label if_fulfilled(this), if_rejected(this, Label::kDeferred), enqueue(this); Branch(IsPromiseStatus(status, v8::Promise::kFulfilled), &if_fulfilled, @@ -426,6 +428,17 @@ void PromiseBuiltinsAssembler::PerformPromiseThen( { var_map.Bind(LoadRoot(RootIndex::kPromiseFulfillReactionJobTaskMap)); var_handler.Bind(on_fulfilled); + + Label use_fallback(this, Label::kDeferred), done(this); + ExtractHandlerContext(on_fulfilled, &var_handler_context); + Branch(IsUndefined(var_handler_context.value()), &use_fallback, &done); + + BIND(&use_fallback); + var_handler_context.Bind(context); + ExtractHandlerContext(on_rejected, &var_handler_context); + Goto(&done); + + BIND(&done); Goto(&enqueue); } @@ -434,6 +447,17 @@ void PromiseBuiltinsAssembler::PerformPromiseThen( CSA_ASSERT(this, IsPromiseStatus(status, v8::Promise::kRejected)); var_map.Bind(LoadRoot(RootIndex::kPromiseRejectReactionJobTaskMap)); var_handler.Bind(on_rejected); + + Label use_fallback(this, Label::kDeferred), done(this); + ExtractHandlerContext(on_rejected, &var_handler_context); + Branch(IsUndefined(var_handler_context.value()), &use_fallback, &done); + + BIND(&use_fallback); + var_handler_context.Bind(context); + ExtractHandlerContext(on_fulfilled, &var_handler_context); + Goto(&done); + BIND(&done); + GotoIf(PromiseHasHandler(promise), &enqueue); CallRuntime(Runtime::kPromiseRevokeReject, context, promise); Goto(&enqueue); @@ -441,9 +465,6 @@ void PromiseBuiltinsAssembler::PerformPromiseThen( BIND(&enqueue); { - VARIABLE(var_handler_context, MachineRepresentation::kTagged, context); - ExtractHandlerContext(var_handler.value(), &var_handler_context); - Node* argument = LoadObjectField(promise, JSPromise::kReactionsOrResultOffset); Node* microtask = AllocatePromiseReactionJobTask( @@ -585,7 +606,36 @@ Node* PromiseBuiltinsAssembler::TriggerPromiseReactions( GotoIf(TaggedIsSmi(current), &done_loop); var_current.Bind(LoadObjectField(current, PromiseReaction::kNextOffset)); - VARIABLE(var_context, MachineRepresentation::kTagged, context); + VARIABLE(var_context, MachineRepresentation::kTagged, + UndefinedConstant()); + + Node* primary_handler; + Node* secondary_handler; + if (type == PromiseReaction::kFulfill) { + primary_handler = + LoadObjectField(current, PromiseReaction::kFulfillHandlerOffset); + secondary_handler = + LoadObjectField(current, PromiseReaction::kRejectHandlerOffset); + } else { + primary_handler = + LoadObjectField(current, PromiseReaction::kRejectHandlerOffset); + secondary_handler = + LoadObjectField(current, PromiseReaction::kFulfillHandlerOffset); + } + + { + Label use_fallback(this, Label::kDeferred), done(this); + ExtractHandlerContext(primary_handler, &var_context); + Branch(IsUndefined(var_context.value()), &use_fallback, &done); + + BIND(&use_fallback); + var_context.Bind(context); + ExtractHandlerContext(secondary_handler, &var_context); + CSA_ASSERT(this, IsNotUndefined(var_context.value())); + Goto(&done); + + BIND(&done); + } // Morph {current} from a PromiseReaction into a PromiseReactionJobTask // and schedule that on the microtask queue. We try to minimize the number @@ -593,9 +643,6 @@ Node* PromiseBuiltinsAssembler::TriggerPromiseReactions( STATIC_ASSERT(static_cast<int>(PromiseReaction::kSize) == static_cast<int>(PromiseReactionJobTask::kSize)); if (type == PromiseReaction::kFulfill) { - Node* handler = - LoadObjectField(current, PromiseReaction::kFulfillHandlerOffset); - ExtractHandlerContext(handler, &var_context); StoreMapNoWriteBarrier(current, RootIndex::kPromiseFulfillReactionJobTaskMap); StoreObjectField(current, PromiseReactionJobTask::kArgumentOffset, @@ -610,9 +657,6 @@ Node* PromiseBuiltinsAssembler::TriggerPromiseReactions( static_cast<int>( PromiseReactionJobTask::kPromiseOrCapabilityOffset)); } else { - Node* handler = - LoadObjectField(current, PromiseReaction::kRejectHandlerOffset); - ExtractHandlerContext(handler, &var_context); StoreMapNoWriteBarrier(current, RootIndex::kPromiseRejectReactionJobTaskMap); StoreObjectField(current, PromiseReactionJobTask::kArgumentOffset, @@ -620,7 +664,7 @@ Node* PromiseBuiltinsAssembler::TriggerPromiseReactions( StoreObjectField(current, PromiseReactionJobTask::kContextOffset, var_context.value()); StoreObjectField(current, PromiseReactionJobTask::kHandlerOffset, - handler); + primary_handler); STATIC_ASSERT( static_cast<int>(PromiseReaction::kPromiseOrCapabilityOffset) == static_cast<int>( @@ -1983,11 +2027,13 @@ TF_BUILTIN(ResolvePromise, PromiseBuiltinsAssembler) { Node* PromiseBuiltinsAssembler::PerformPromiseAll( Node* context, Node* constructor, Node* capability, - const IteratorRecord& iterator, Label* if_exception, - Variable* var_exception) { + const IteratorRecord& iterator, + const PromiseAllResolvingElementFunction& create_resolve_element_function, + const PromiseAllResolvingElementFunction& create_reject_element_function, + Label* if_exception, Variable* var_exception) { IteratorBuiltinsAssembler iter_assembler(state()); - Node* const native_context = LoadNativeContext(context); + TNode<NativeContext> native_context = Cast(LoadNativeContext(context)); // For catch prediction, don't treat the .then calls as handling it; // instead, recurse outwards. @@ -1995,8 +2041,8 @@ Node* PromiseBuiltinsAssembler::PerformPromiseAll( native_context, IsDebugActive(), LoadObjectField(capability, PromiseCapability::kRejectOffset)); - Node* const resolve_element_context = - CreatePromiseAllResolveElementContext(capability, native_context); + TNode<Context> resolve_element_context = + Cast(CreatePromiseAllResolveElementContext(capability, native_context)); TVARIABLE(Smi, var_index, SmiConstant(1)); Label loop(this, &var_index), done_loop(this), @@ -2051,8 +2097,10 @@ Node* PromiseBuiltinsAssembler::PerformPromiseAll( // Set resolveElement.[[Values]] to values. // Set resolveElement.[[Capability]] to resultCapability. // Set resolveElement.[[RemainingElements]] to remainingElementsCount. - Node* const resolve_element_fun = CreatePromiseAllResolveElementFunction( - resolve_element_context, index, native_context); + Node* const resolve_element_fun = create_resolve_element_function( + resolve_element_context, index, native_context, Cast(capability)); + Node* const reject_element_fun = create_reject_element_function( + resolve_element_context, index, native_context, Cast(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 @@ -2087,10 +2135,8 @@ Node* PromiseBuiltinsAssembler::PerformPromiseAll( // Register the PromiseReaction immediately on the {next_value}, not // passing any chained promise since neither async_hooks nor DevTools // are enabled, so there's no use of the resulting promise. - PerformPromiseThen( - native_context, next_value, resolve_element_fun, - LoadObjectField(capability, PromiseCapability::kRejectOffset), - UndefinedConstant()); + PerformPromiseThen(native_context, next_value, resolve_element_fun, + reject_element_fun, UndefinedConstant()); Goto(&loop); } @@ -2111,7 +2157,7 @@ Node* PromiseBuiltinsAssembler::PerformPromiseAll( CallJS(CodeFactory::Call(isolate(), ConvertReceiverMode::kNotNullOrUndefined), native_context, then, next_promise, resolve_element_fun, - LoadObjectField(capability, PromiseCapability::kRejectOffset)); + reject_element_fun); GotoIfException(then_call, &close_iterator, var_exception); // For catch prediction, mark that rejections here are semantically @@ -2215,15 +2261,14 @@ Node* PromiseBuiltinsAssembler::PerformPromiseAll( return promise; } -// ES#sec-promise.all -// Promise.all ( iterable ) -TF_BUILTIN(PromiseAll, PromiseBuiltinsAssembler) { +void PromiseBuiltinsAssembler::Generate_PromiseAll( + TNode<Context> context, TNode<Object> receiver, TNode<Object> iterable, + const PromiseAllResolvingElementFunction& create_resolve_element_function, + const PromiseAllResolvingElementFunction& create_reject_element_function) { IteratorBuiltinsAssembler iter_assembler(state()); // Let C be the this value. // If Type(C) is not Object, throw a TypeError exception. - Node* const receiver = Parameter(Descriptor::kReceiver); - Node* const context = Parameter(Descriptor::kContext); ThrowIfNotJSReceiver(context, receiver, MessageTemplate::kCalledOnNonObject, "Promise.all"); @@ -2239,7 +2284,6 @@ TF_BUILTIN(PromiseAll, PromiseBuiltinsAssembler) { // Let iterator be GetIterator(iterable). // IfAbruptRejectPromise(iterator, promiseCapability). - Node* const iterable = Parameter(Descriptor::kIterable); IteratorRecord iterator = iter_assembler.GetIterator( context, iterable, &reject_promise, &var_exception); @@ -2249,7 +2293,8 @@ TF_BUILTIN(PromiseAll, PromiseBuiltinsAssembler) { // IteratorClose(iterator, result). // IfAbruptRejectPromise(result, promiseCapability). Node* const result = PerformPromiseAll( - context, receiver, capability, iterator, &reject_promise, &var_exception); + context, receiver, capability, iterator, create_resolve_element_function, + create_reject_element_function, &reject_promise, &var_exception); Return(result); @@ -2268,11 +2313,55 @@ TF_BUILTIN(PromiseAll, PromiseBuiltinsAssembler) { } } -TF_BUILTIN(PromiseAllResolveElementClosure, PromiseBuiltinsAssembler) { - TNode<Object> value = CAST(Parameter(Descriptor::kValue)); - TNode<Context> context = CAST(Parameter(Descriptor::kContext)); - TNode<JSFunction> function = CAST(Parameter(Descriptor::kJSTarget)); +// ES#sec-promise.all +// Promise.all ( iterable ) +TF_BUILTIN(PromiseAll, PromiseBuiltinsAssembler) { + TNode<Object> receiver = Cast(Parameter(Descriptor::kReceiver)); + TNode<Context> context = Cast(Parameter(Descriptor::kContext)); + TNode<Object> iterable = Cast(Parameter(Descriptor::kIterable)); + Generate_PromiseAll( + context, receiver, iterable, + [this](TNode<Context> context, TNode<Smi> index, + TNode<NativeContext> native_context, + TNode<PromiseCapability> capability) { + return CreatePromiseAllResolveElementFunction( + context, index, native_context, + Context::PROMISE_ALL_RESOLVE_ELEMENT_SHARED_FUN); + }, + [this](TNode<Context> context, TNode<Smi> index, + TNode<NativeContext> native_context, + TNode<PromiseCapability> capability) { + return LoadObjectField(capability, PromiseCapability::kRejectOffset); + }); +} +// ES#sec-promise.allsettled +// Promise.allSettled ( iterable ) +TF_BUILTIN(PromiseAllSettled, PromiseBuiltinsAssembler) { + TNode<Object> receiver = Cast(Parameter(Descriptor::kReceiver)); + TNode<Context> context = Cast(Parameter(Descriptor::kContext)); + TNode<Object> iterable = Cast(Parameter(Descriptor::kIterable)); + Generate_PromiseAll( + context, receiver, iterable, + [this](TNode<Context> context, TNode<Smi> index, + TNode<NativeContext> native_context, + TNode<PromiseCapability> capability) { + return CreatePromiseAllResolveElementFunction( + context, index, native_context, + Context::PROMISE_ALL_SETTLED_RESOLVE_ELEMENT_SHARED_FUN); + }, + [this](TNode<Context> context, TNode<Smi> index, + TNode<NativeContext> native_context, + TNode<PromiseCapability> capability) { + return CreatePromiseAllResolveElementFunction( + context, index, native_context, + Context::PROMISE_ALL_SETTLED_REJECT_ELEMENT_SHARED_FUN); + }); +} + +void PromiseBuiltinsAssembler::Generate_PromiseAllResolveElementClosure( + TNode<Context> context, TNode<Object> value, TNode<JSFunction> function, + const CreatePromiseAllResolveElementFunctionValue& callback) { Label already_called(this, Label::kDeferred), resolve_promise(this); // We use the {function}s context as the marker to remember whether this @@ -2285,9 +2374,13 @@ TF_BUILTIN(PromiseAllResolveElementClosure, PromiseBuiltinsAssembler) { this, SmiEqual(LoadObjectField<Smi>(context, Context::kLengthOffset), SmiConstant(PromiseBuiltins::kPromiseAllResolveElementLength))); - TNode<Context> native_context = LoadNativeContext(context); + TNode<NativeContext> native_context = Cast(LoadNativeContext(context)); StoreObjectField(function, JSFunction::kContextOffset, native_context); + // Update the value depending on whether Promise.all or + // Promise.allSettled is called. + value = callback(context, native_context, value); + // Determine the index from the {function}. Label unreachable(this, Label::kDeferred); STATIC_ASSERT(PropertyArray::kNoHashSentinel == 0); @@ -2382,6 +2475,80 @@ TF_BUILTIN(PromiseAllResolveElementClosure, PromiseBuiltinsAssembler) { Unreachable(); } +TF_BUILTIN(PromiseAllResolveElementClosure, PromiseBuiltinsAssembler) { + TNode<Object> value = CAST(Parameter(Descriptor::kValue)); + TNode<Context> context = CAST(Parameter(Descriptor::kContext)); + TNode<JSFunction> function = CAST(Parameter(Descriptor::kJSTarget)); + + Generate_PromiseAllResolveElementClosure( + context, value, function, + [](TNode<Object>, TNode<NativeContext>, TNode<Object> value) { + return value; + }); +} + +TF_BUILTIN(PromiseAllSettledResolveElementClosure, PromiseBuiltinsAssembler) { + TNode<Object> value = CAST(Parameter(Descriptor::kValue)); + TNode<Context> context = CAST(Parameter(Descriptor::kContext)); + TNode<JSFunction> function = CAST(Parameter(Descriptor::kJSTarget)); + + Generate_PromiseAllResolveElementClosure( + context, value, function, + [this](TNode<Context> context, TNode<NativeContext> native_context, + TNode<Object> value) { + // TODO(gsathya): Optimize the creation using a cached map to + // prevent transitions here. + // 9. Let obj be ! ObjectCreate(%ObjectPrototype%). + TNode<HeapObject> object_function = Cast( + LoadContextElement(native_context, Context::OBJECT_FUNCTION_INDEX)); + TNode<Map> object_function_map = Cast(LoadObjectField( + object_function, JSFunction::kPrototypeOrInitialMapOffset)); + TNode<JSObject> obj = + Cast(AllocateJSObjectFromMap(object_function_map)); + + // 10. Perform ! CreateDataProperty(obj, "status", "fulfilled"). + CallBuiltin(Builtins::kFastCreateDataProperty, context, obj, + StringConstant("status"), StringConstant("fulfilled")); + + // 11. Perform ! CreateDataProperty(obj, "value", x). + CallBuiltin(Builtins::kFastCreateDataProperty, context, obj, + StringConstant("value"), value); + + return obj; + }); +} + +TF_BUILTIN(PromiseAllSettledRejectElementClosure, PromiseBuiltinsAssembler) { + TNode<Object> value = CAST(Parameter(Descriptor::kValue)); + TNode<Context> context = CAST(Parameter(Descriptor::kContext)); + TNode<JSFunction> function = CAST(Parameter(Descriptor::kJSTarget)); + + Generate_PromiseAllResolveElementClosure( + context, value, function, + [this](TNode<Context> context, TNode<NativeContext> native_context, + TNode<Object> value) { + // TODO(gsathya): Optimize the creation using a cached map to + // prevent transitions here. + // 9. Let obj be ! ObjectCreate(%ObjectPrototype%). + TNode<HeapObject> object_function = Cast( + LoadContextElement(native_context, Context::OBJECT_FUNCTION_INDEX)); + TNode<Map> object_function_map = Cast(LoadObjectField( + object_function, JSFunction::kPrototypeOrInitialMapOffset)); + TNode<JSObject> obj = + Cast(AllocateJSObjectFromMap(object_function_map)); + + // 10. Perform ! CreateDataProperty(obj, "status", "rejected"). + CallBuiltin(Builtins::kFastCreateDataProperty, context, obj, + StringConstant("status"), StringConstant("rejected")); + + // 11. Perform ! CreateDataProperty(obj, "reason", x). + CallBuiltin(Builtins::kFastCreateDataProperty, context, obj, + StringConstant("reason"), value); + + return obj; + }); +} + // ES#sec-promise.race // Promise.race ( iterable ) TF_BUILTIN(PromiseRace, PromiseBuiltinsAssembler) { diff --git a/deps/v8/src/builtins/builtins-promise-gen.h b/deps/v8/src/builtins/builtins-promise-gen.h index 6bb38ee4eb..b0555b2594 100644 --- a/deps/v8/src/builtins/builtins-promise-gen.h +++ b/deps/v8/src/builtins/builtins-promise-gen.h @@ -15,7 +15,7 @@ namespace internal { typedef compiler::CodeAssemblerState CodeAssemblerState; -class PromiseBuiltinsAssembler : public CodeStubAssembler { +class V8_EXPORT_PRIVATE PromiseBuiltinsAssembler : public CodeStubAssembler { public: explicit PromiseBuiltinsAssembler(compiler::CodeAssemblerState* state) : CodeStubAssembler(state) {} @@ -62,8 +62,10 @@ class PromiseBuiltinsAssembler : public CodeStubAssembler { // case to mark it's done). Node* CreatePromiseAllResolveElementContext(Node* promise_capability, Node* native_context); - Node* CreatePromiseAllResolveElementFunction(Node* context, TNode<Smi> index, - Node* native_context); + TNode<JSFunction> CreatePromiseAllResolveElementFunction(Node* context, + TNode<Smi> index, + Node* native_context, + int slot_index); Node* CreatePromiseResolvingFunctionsContext(Node* promise, Node* debug_event, Node* native_context); @@ -129,9 +131,16 @@ class PromiseBuiltinsAssembler : public CodeStubAssembler { Node* CreateThrowerFunction(Node* reason, Node* native_context); + typedef std::function<TNode<Object>(TNode<Context> context, TNode<Smi> index, + TNode<NativeContext> native_context, + TNode<PromiseCapability> capability)> + PromiseAllResolvingElementFunction; + Node* PerformPromiseAll( Node* context, Node* constructor, Node* capability, const IteratorBuiltinsFromDSLAssembler::IteratorRecord& record, + const PromiseAllResolvingElementFunction& create_resolve_element_function, + const PromiseAllResolvingElementFunction& create_reject_element_function, Label* if_exception, Variable* var_exception); void SetForwardingHandlerIfTrue(Node* context, Node* condition, @@ -156,6 +165,19 @@ class PromiseBuiltinsAssembler : public CodeStubAssembler { Node* AllocateJSPromise(Node* context); void ExtractHandlerContext(Node* handler, Variable* var_context); + void Generate_PromiseAll( + TNode<Context> context, TNode<Object> receiver, TNode<Object> iterable, + const PromiseAllResolvingElementFunction& create_resolve_element_function, + const PromiseAllResolvingElementFunction& create_reject_element_function); + + typedef std::function<TNode<Object>(TNode<Context> context, + TNode<NativeContext> native_context, + TNode<Object> value)> + CreatePromiseAllResolveElementFunctionValue; + + void Generate_PromiseAllResolveElementClosure( + TNode<Context> context, TNode<Object> value, TNode<JSFunction> function, + const CreatePromiseAllResolveElementFunctionValue& callback); }; } // namespace internal diff --git a/deps/v8/src/builtins/builtins-proxy-gen.cc b/deps/v8/src/builtins/builtins-proxy-gen.cc index c5b1037dcb..825e229451 100644 --- a/deps/v8/src/builtins/builtins-proxy-gen.cc +++ b/deps/v8/src/builtins/builtins-proxy-gen.cc @@ -13,15 +13,6 @@ namespace v8 { namespace internal { -void ProxiesCodeStubAssembler::GotoIfRevokedProxy(Node* object, - Label* if_proxy_revoked) { - Label proxy_not_revoked(this); - GotoIfNot(IsJSProxy(object), &proxy_not_revoked); - Branch(IsJSReceiver(CAST(LoadObjectField(object, JSProxy::kHandlerOffset))), - &proxy_not_revoked, if_proxy_revoked); - BIND(&proxy_not_revoked); -} - Node* ProxiesCodeStubAssembler::AllocateProxy(Node* target, Node* handler, Node* context) { VARIABLE(map, MachineRepresentation::kTagged); @@ -145,139 +136,9 @@ Node* ProxiesCodeStubAssembler::AllocateProxyRevokeFunction(Node* proxy, proxy_context); } -// ES #sec-proxy-constructor -TF_BUILTIN(ProxyConstructor, ProxiesCodeStubAssembler) { - Node* context = Parameter(Descriptor::kContext); - - // 1. If NewTarget is undefined, throw a TypeError exception. - Node* new_target = Parameter(Descriptor::kJSNewTarget); - Label throwtypeerror(this, Label::kDeferred), createproxy(this); - Branch(IsUndefined(new_target), &throwtypeerror, &createproxy); - - BIND(&throwtypeerror); - { - ThrowTypeError(context, MessageTemplate::kConstructorNotFunction, "Proxy"); - } - - // 2. Return ? ProxyCreate(target, handler). - BIND(&createproxy); - { - // https://tc39.github.io/ecma262/#sec-proxycreate - Node* target = Parameter(Descriptor::kTarget); - Node* handler = Parameter(Descriptor::kHandler); - - // 1. If Type(target) is not Object, throw a TypeError exception. - // 2. If target is a Proxy exotic object and target.[[ProxyHandler]] is - // null, throw a TypeError exception. - // 3. If Type(handler) is not Object, throw a TypeError exception. - // 4. If handler is a Proxy exotic object and handler.[[ProxyHandler]] - // is null, throw a TypeError exception. - Label throw_proxy_non_object(this, Label::kDeferred), - throw_proxy_handler_or_target_revoked(this, Label::kDeferred), - return_create_proxy(this); - - GotoIf(TaggedIsSmi(target), &throw_proxy_non_object); - GotoIfNot(IsJSReceiver(target), &throw_proxy_non_object); - GotoIfRevokedProxy(target, &throw_proxy_handler_or_target_revoked); - - GotoIf(TaggedIsSmi(handler), &throw_proxy_non_object); - GotoIfNot(IsJSReceiver(handler), &throw_proxy_non_object); - GotoIfRevokedProxy(handler, &throw_proxy_handler_or_target_revoked); - - // 5. Let P be a newly created object. - // 6. Set P's essential internal methods (except for [[Call]] and - // [[Construct]]) to the definitions specified in 9.5. - // 7. If IsCallable(target) is true, then - // a. Set P.[[Call]] as specified in 9.5.12. - // b. If IsConstructor(target) is true, then - // 1. Set P.[[Construct]] as specified in 9.5.13. - // 8. Set P.[[ProxyTarget]] to target. - // 9. Set P.[[ProxyHandler]] to handler. - // 10. Return P. - Return(AllocateProxy(target, handler, context)); - - BIND(&throw_proxy_non_object); - ThrowTypeError(context, MessageTemplate::kProxyNonObject); - - BIND(&throw_proxy_handler_or_target_revoked); - ThrowTypeError(context, MessageTemplate::kProxyHandlerOrTargetRevoked); - } -} - -TF_BUILTIN(ProxyRevocable, ProxiesCodeStubAssembler) { - Node* const target = Parameter(Descriptor::kTarget); - Node* const handler = Parameter(Descriptor::kHandler); - Node* const context = Parameter(Descriptor::kContext); - Node* const native_context = LoadNativeContext(context); - - Label throw_proxy_non_object(this, Label::kDeferred), - throw_proxy_handler_or_target_revoked(this, Label::kDeferred), - return_create_proxy(this); - - GotoIf(TaggedIsSmi(target), &throw_proxy_non_object); - GotoIfNot(IsJSReceiver(target), &throw_proxy_non_object); - GotoIfRevokedProxy(target, &throw_proxy_handler_or_target_revoked); - - GotoIf(TaggedIsSmi(handler), &throw_proxy_non_object); - GotoIfNot(IsJSReceiver(handler), &throw_proxy_non_object); - GotoIfRevokedProxy(handler, &throw_proxy_handler_or_target_revoked); - - Node* const proxy = AllocateProxy(target, handler, context); - Node* const revoke = AllocateProxyRevokeFunction(proxy, context); - - Node* const result = Allocate(JSProxyRevocableResult::kSize); - Node* const result_map = LoadContextElement( - native_context, Context::PROXY_REVOCABLE_RESULT_MAP_INDEX); - StoreMapNoWriteBarrier(result, result_map); - StoreObjectFieldRoot(result, JSProxyRevocableResult::kPropertiesOrHashOffset, - RootIndex::kEmptyFixedArray); - StoreObjectFieldRoot(result, JSProxyRevocableResult::kElementsOffset, - RootIndex::kEmptyFixedArray); - StoreObjectFieldNoWriteBarrier(result, JSProxyRevocableResult::kProxyOffset, - proxy); - StoreObjectFieldNoWriteBarrier(result, JSProxyRevocableResult::kRevokeOffset, - revoke); - Return(result); - - BIND(&throw_proxy_non_object); - ThrowTypeError(context, MessageTemplate::kProxyNonObject); - - BIND(&throw_proxy_handler_or_target_revoked); - ThrowTypeError(context, MessageTemplate::kProxyHandlerOrTargetRevoked); -} - -// Proxy Revocation Functions -// https://tc39.github.io/ecma262/#sec-proxy-revocation-functions -TF_BUILTIN(ProxyRevoke, ProxiesCodeStubAssembler) { - Node* const context = Parameter(Descriptor::kContext); - - // 1. Let p be F.[[RevocableProxy]]. - Node* const proxy_slot = IntPtrConstant(kProxySlot); - Node* const proxy = LoadContextElement(context, proxy_slot); - - Label revoke_called(this); - - // 2. If p is null, ... - GotoIf(IsNull(proxy), &revoke_called); - - // 3. Set F.[[RevocableProxy]] to null. - StoreContextElement(context, proxy_slot, NullConstant()); - - // 4. Assert: p is a Proxy object. - CSA_ASSERT(this, IsJSProxy(proxy)); - - // 5. Set p.[[ProxyTarget]] to null. - StoreObjectField(proxy, JSProxy::kTargetOffset, NullConstant()); - - // 6. Set p.[[ProxyHandler]] to null. - StoreObjectField(proxy, JSProxy::kHandlerOffset, NullConstant()); - - // 7. Return undefined. - Return(UndefinedConstant()); - - BIND(&revoke_called); - // 2. ... return undefined. - Return(UndefinedConstant()); +Node* ProxiesCodeStubAssembler::GetProxyConstructorJSNewTarget() { + return CodeAssembler::Parameter(static_cast<int>( + Builtin_ProxyConstructor_InterfaceDescriptor::kJSNewTarget)); } TF_BUILTIN(CallProxy, ProxiesCodeStubAssembler) { diff --git a/deps/v8/src/builtins/builtins-proxy-gen.h b/deps/v8/src/builtins/builtins-proxy-gen.h index 95845fca4e..01479d9999 100644 --- a/deps/v8/src/builtins/builtins-proxy-gen.h +++ b/deps/v8/src/builtins/builtins-proxy-gen.h @@ -7,6 +7,7 @@ #include "src/code-stub-assembler.h" #include "src/objects/js-proxy.h" +#include "torque-generated/builtins-proxy-from-dsl-gen.h" namespace v8 { namespace internal { @@ -27,18 +28,22 @@ class ProxiesCodeStubAssembler : public CodeStubAssembler { Node* ProxySetProperty(Node* context, Node* proxy, Node* name, Node* value, Node* receiver); + Node* AllocateProxy(Node* target, Node* handler, Node* context); + Node* AllocateProxyRevokeFunction(Node* proxy, Node* context); + + // Get JSNewTarget parameter for ProxyConstructor builtin (Torque). + // TODO(v8:9120): Remove this once torque support exists + Node* GetProxyConstructorJSNewTarget(); + protected: enum ProxyRevokeFunctionContextSlot { kProxySlot = Context::MIN_CONTEXT_SLOTS, kProxyContextLength, }; - void GotoIfRevokedProxy(Node* object, Label* if_proxy_revoked); - Node* AllocateProxy(Node* target, Node* handler, Node* context); Node* AllocateJSArrayForCodeStubArguments(Node* context, CodeStubArguments& args, Node* argc, ParameterMode mode); - Node* AllocateProxyRevokeFunction(Node* proxy, Node* context); void CheckHasTrapResult(Node* context, Node* target, Node* proxy, Node* name, Label* check_passed, Label* if_bailout); diff --git a/deps/v8/src/builtins/builtins-regexp-gen.cc b/deps/v8/src/builtins/builtins-regexp-gen.cc index 00b1f1b921..1a0e014e3e 100644 --- a/deps/v8/src/builtins/builtins-regexp-gen.cc +++ b/deps/v8/src/builtins/builtins-regexp-gen.cc @@ -538,10 +538,12 @@ TNode<HeapObject> RegExpBuiltinsAssembler::RegExpExecInternal( IntPtrAdd(BitcastTaggedToWord(code), IntPtrConstant(Code::kHeaderSize - kHeapObjectTag))); - TNode<Int32T> result = UncheckedCast<Int32T>(CallCFunction9( - retval_type, arg0_type, arg1_type, arg2_type, arg3_type, arg4_type, - arg5_type, arg6_type, arg7_type, arg8_type, code_entry, arg0, arg1, - arg2, arg3, arg4, arg5, arg6, arg7, arg8)); + TNode<Int32T> result = UncheckedCast<Int32T>(CallCFunction( + code_entry, retval_type, std::make_pair(arg0_type, arg0), + std::make_pair(arg1_type, arg1), std::make_pair(arg2_type, arg2), + std::make_pair(arg3_type, arg3), std::make_pair(arg4_type, arg4), + std::make_pair(arg5_type, arg5), std::make_pair(arg6_type, arg6), + std::make_pair(arg7_type, arg7), std::make_pair(arg8_type, arg8))); // Check the result. // We expect exactly one result since we force the called regexp to behave @@ -779,6 +781,14 @@ RegExpBuiltinsAssembler::RegExpPrototypeExecBodyWithoutResult( return CAST(var_result.value()); } +TNode<RegExpMatchInfo> +RegExpBuiltinsAssembler::RegExpPrototypeExecBodyWithoutResultFast( + TNode<Context> context, TNode<JSReceiver> maybe_regexp, + TNode<String> string, Label* if_didnotmatch) { + return RegExpPrototypeExecBodyWithoutResult(context, maybe_regexp, string, + if_didnotmatch, true); +} + // ES#sec-regexp.prototype.exec // RegExp.prototype.exec ( string ) TNode<HeapObject> RegExpBuiltinsAssembler::RegExpPrototypeExecBody( @@ -1821,6 +1831,8 @@ Node* RegExpBuiltinsAssembler::AdvanceStringIndex(Node* const string, if (is_fastpath) CSA_ASSERT(this, TaggedIsPositiveSmi(index)); // Default to last_index + 1. + // TODO(pwong): Consider using TrySmiAdd for the fast path to reduce generated + // code. Node* const index_plus_one = NumberInc(index); VARIABLE(var_result, MachineRepresentation::kTagged, index_plus_one); @@ -2880,217 +2892,6 @@ Node* RegExpBuiltinsAssembler::ReplaceGlobalCallableFastPath( return var_result.value(); } -Node* RegExpBuiltinsAssembler::ReplaceSimpleStringFastPath( - Node* context, Node* regexp, TNode<String> string, - TNode<String> replace_string) { - // The fast path is reached only if {receiver} is an unmodified - // JSRegExp instance, {replace_value} is non-callable, and - // ToString({replace_value}) does not contain '$', i.e. we're doing a simple - // string replacement. - - CSA_ASSERT(this, IsFastRegExp(context, regexp)); - - const bool kIsFastPath = true; - - TVARIABLE(String, var_result, EmptyStringConstant()); - VARIABLE(var_last_match_end, MachineRepresentation::kTagged, SmiZero()); - VARIABLE(var_is_unicode, MachineRepresentation::kWord32, Int32Constant(0)); - Variable* vars[] = {&var_result, &var_last_match_end}; - Label out(this), loop(this, 2, vars), loop_end(this), - if_nofurthermatches(this); - - // Is {regexp} global? - Node* const is_global = FastFlagGetter(CAST(regexp), JSRegExp::kGlobal); - GotoIfNot(is_global, &loop); - - var_is_unicode.Bind(FastFlagGetter(CAST(regexp), JSRegExp::kUnicode)); - FastStoreLastIndex(regexp, SmiZero()); - Goto(&loop); - - BIND(&loop); - { - TNode<RegExpMatchInfo> var_match_indices = - RegExpPrototypeExecBodyWithoutResult(CAST(context), CAST(regexp), - string, &if_nofurthermatches, - kIsFastPath); - - // Successful match. - { - TNode<Smi> const match_start = CAST(UnsafeLoadFixedArrayElement( - var_match_indices, RegExpMatchInfo::kFirstCaptureIndex)); - TNode<Smi> const match_end = CAST(UnsafeLoadFixedArrayElement( - var_match_indices, RegExpMatchInfo::kFirstCaptureIndex + 1)); - - TNode<Smi> const replace_length = LoadStringLengthAsSmi(replace_string); - - // TODO(jgruber): We could skip many of the checks that using SubString - // here entails. - TNode<String> first_part = - CAST(CallBuiltin(Builtins::kSubString, context, string, - var_last_match_end.value(), match_start)); - var_result = CAST(CallBuiltin(Builtins::kStringAdd_CheckNone, context, - var_result.value(), first_part)); - - GotoIf(SmiEqual(replace_length, SmiZero()), &loop_end); - - var_result = CAST(CallBuiltin(Builtins::kStringAdd_CheckNone, context, - var_result.value(), replace_string)); - Goto(&loop_end); - - BIND(&loop_end); - { - var_last_match_end.Bind(match_end); - // Non-global case ends here after the first replacement. - GotoIfNot(is_global, &if_nofurthermatches); - - GotoIf(SmiNotEqual(match_end, match_start), &loop); - // If match is the empty string, we have to increment lastIndex. - Node* const this_index = FastLoadLastIndex(CAST(regexp)); - Node* const next_index = AdvanceStringIndex( - string, this_index, var_is_unicode.value(), kIsFastPath); - FastStoreLastIndex(regexp, next_index); - Goto(&loop); - } - } - } - - BIND(&if_nofurthermatches); - { - TNode<Smi> const string_length = LoadStringLengthAsSmi(string); - TNode<String> last_part = - CAST(CallBuiltin(Builtins::kSubString, context, string, - var_last_match_end.value(), string_length)); - var_result = CAST(CallBuiltin(Builtins::kStringAdd_CheckNone, context, - var_result.value(), last_part)); - Goto(&out); - } - - BIND(&out); - return var_result.value(); -} - -// Helper that skips a few initial checks. -TF_BUILTIN(RegExpReplace, RegExpBuiltinsAssembler) { - TNode<JSRegExp> regexp = CAST(Parameter(Descriptor::kRegExp)); - TNode<String> string = CAST(Parameter(Descriptor::kString)); - TNode<Object> replace_value = CAST(Parameter(Descriptor::kReplaceValue)); - TNode<Context> context = CAST(Parameter(Descriptor::kContext)); - - CSA_ASSERT(this, IsFastRegExp(context, regexp)); - - Label checkreplacestring(this), if_iscallable(this), - runtime(this, Label::kDeferred); - - // 2. Is {replace_value} callable? - GotoIf(TaggedIsSmi(replace_value), &checkreplacestring); - Branch(IsCallableMap(LoadMap(CAST(replace_value))), &if_iscallable, - &checkreplacestring); - - // 3. Does ToString({replace_value}) contain '$'? - BIND(&checkreplacestring); - { - TNode<String> const replace_string = - ToString_Inline(context, replace_value); - - // ToString(replaceValue) could potentially change the shape of the RegExp - // object. Recheck that we are still on the fast path and bail to runtime - // otherwise. - { - Label next(this); - BranchIfFastRegExp(context, regexp, &next, &runtime); - BIND(&next); - } - - TNode<String> const dollar_string = HeapConstant( - isolate()->factory()->LookupSingleCharacterStringFromCode('$')); - TNode<Smi> const dollar_ix = - CAST(CallBuiltin(Builtins::kStringIndexOf, context, replace_string, - dollar_string, SmiZero())); - GotoIfNot(SmiEqual(dollar_ix, SmiConstant(-1)), &runtime); - - Return( - ReplaceSimpleStringFastPath(context, regexp, string, replace_string)); - } - - // {regexp} is unmodified and {replace_value} is callable. - BIND(&if_iscallable); - { - Node* const replace_fn = replace_value; - - // Check if the {regexp} is global. - Label if_isglobal(this), if_isnotglobal(this); - - Node* const is_global = FastFlagGetter(regexp, JSRegExp::kGlobal); - Branch(is_global, &if_isglobal, &if_isnotglobal); - - BIND(&if_isglobal); - Return(ReplaceGlobalCallableFastPath(context, regexp, string, replace_fn)); - - BIND(&if_isnotglobal); - Return(CallRuntime(Runtime::kStringReplaceNonGlobalRegExpWithFunction, - context, string, regexp, replace_fn)); - } - - BIND(&runtime); - Return(CallRuntime(Runtime::kRegExpReplace, context, regexp, string, - replace_value)); -} - -// ES#sec-regexp.prototype-@@replace -// RegExp.prototype [ @@replace ] ( string, replaceValue ) -TF_BUILTIN(RegExpPrototypeReplace, RegExpBuiltinsAssembler) { - const int kStringArg = 0; - const int kReplaceValueArg = 1; - - TNode<IntPtrT> argc = - ChangeInt32ToIntPtr(Parameter(Descriptor::kJSActualArgumentsCount)); - CodeStubArguments args(this, argc); - - TNode<Object> maybe_receiver = args.GetReceiver(); - TNode<Object> maybe_string = args.GetOptionalArgumentValue(kStringArg); - TNode<Object> replace_value = args.GetOptionalArgumentValue(kReplaceValueArg); - TNode<Context> context = CAST(Parameter(Descriptor::kContext)); - - // RegExpPrototypeReplace is a bit of a beast - a summary of dispatch logic: - // - // if (!IsFastRegExp(receiver)) CallRuntime(RegExpReplace) - // if (IsCallable(replace)) { - // if (IsGlobal(receiver)) { - // // Called 'fast-path' but contains several runtime calls. - // ReplaceGlobalCallableFastPath() - // } else { - // CallRuntime(StringReplaceNonGlobalRegExpWithFunction) - // } - // } else { - // if (replace.contains("$")) { - // CallRuntime(RegExpReplace) - // } else { - // ReplaceSimpleStringFastPath() - // } - // } - - // Ensure {maybe_receiver} is a JSReceiver. - ThrowIfNotJSReceiver(context, maybe_receiver, - MessageTemplate::kIncompatibleMethodReceiver, - "RegExp.prototype.@@replace"); - Node* const receiver = maybe_receiver; - - // Convert {maybe_string} to a String. - TNode<String> const string = ToString_Inline(context, maybe_string); - - // Fast-path checks: 1. Is the {receiver} an unmodified JSRegExp instance? - Label stub(this), runtime(this, Label::kDeferred); - BranchIfFastRegExp(context, receiver, &stub, &runtime); - - BIND(&stub); - args.PopAndReturn(CallBuiltin(Builtins::kRegExpReplace, context, receiver, - string, replace_value)); - - BIND(&runtime); - args.PopAndReturn(CallRuntime(Runtime::kRegExpReplace, context, receiver, - string, replace_value)); -} - class RegExpStringIteratorAssembler : public RegExpBuiltinsAssembler { public: explicit RegExpStringIteratorAssembler(compiler::CodeAssemblerState* state) diff --git a/deps/v8/src/builtins/builtins-regexp-gen.h b/deps/v8/src/builtins/builtins-regexp-gen.h index 8f96ba38a6..879138867b 100644 --- a/deps/v8/src/builtins/builtins-regexp-gen.h +++ b/deps/v8/src/builtins/builtins-regexp-gen.h @@ -32,7 +32,6 @@ class RegExpBuiltinsAssembler : public CodeStubAssembler { TNode<BoolT> IsRegExp(TNode<Context> context, TNode<Object> maybe_receiver); - protected: TNode<Smi> SmiZero(); TNode<IntPtrT> IntPtrZero(); @@ -75,6 +74,10 @@ class RegExpBuiltinsAssembler : public CodeStubAssembler { TNode<RegExpMatchInfo> RegExpPrototypeExecBodyWithoutResult( TNode<Context> context, TNode<JSReceiver> maybe_regexp, TNode<String> string, Label* if_didnotmatch, const bool is_fastpath); + TNode<RegExpMatchInfo> RegExpPrototypeExecBodyWithoutResultFast( + TNode<Context> context, TNode<JSReceiver> maybe_regexp, + TNode<String> string, Label* if_didnotmatch); + TNode<HeapObject> RegExpPrototypeExecBody(TNode<Context> context, TNode<JSReceiver> maybe_regexp, TNode<String> string, @@ -106,6 +109,12 @@ class RegExpBuiltinsAssembler : public CodeStubAssembler { Node* FlagsGetter(Node* const context, Node* const regexp, bool is_fastpath); TNode<Int32T> FastFlagGetter(TNode<JSRegExp> regexp, JSRegExp::Flag flag); + TNode<BoolT> FastFlagGetterGlobal(TNode<JSRegExp> regexp) { + return ReinterpretCast<BoolT>(FastFlagGetter(regexp, JSRegExp::kGlobal)); + } + TNode<BoolT> FastFlagGetterUnicode(TNode<JSRegExp> regexp) { + return ReinterpretCast<BoolT>(FastFlagGetter(regexp, JSRegExp::kUnicode)); + } TNode<Int32T> SlowFlagGetter(TNode<Context> context, TNode<Object> regexp, JSRegExp::Flag flag); TNode<Int32T> FlagGetter(TNode<Context> context, TNode<Object> regexp, @@ -122,6 +131,11 @@ class RegExpBuiltinsAssembler : public CodeStubAssembler { Node* AdvanceStringIndex(Node* const string, Node* const index, Node* const is_unicode, bool is_fastpath); + Node* AdvanceStringIndexFast(Node* const string, Node* const index, + Node* const is_unicode) { + return AdvanceStringIndex(string, index, is_unicode, true); + } + void RegExpPrototypeMatchBody(Node* const context, Node* const regexp, TNode<String> const string, const bool is_fastpath); @@ -137,9 +151,6 @@ class RegExpBuiltinsAssembler : public CodeStubAssembler { Node* ReplaceGlobalCallableFastPath(Node* context, Node* regexp, Node* string, Node* replace_callable); - Node* ReplaceSimpleStringFastPath(Node* context, Node* regexp, - TNode<String> string, - TNode<String> replace_string); }; class RegExpMatchAllAssembler : public RegExpBuiltinsAssembler { diff --git a/deps/v8/src/builtins/builtins-string-gen.cc b/deps/v8/src/builtins/builtins-string-gen.cc index e2db979452..74b2db0542 100644 --- a/deps/v8/src/builtins/builtins-string-gen.cc +++ b/deps/v8/src/builtins/builtins-string-gen.cc @@ -107,10 +107,13 @@ Node* StringBuiltinsAssembler::CallSearchStringRaw(Node* const subject_ptr, MachineType type_ptr = MachineType::Pointer(); MachineType type_intptr = MachineType::IntPtr(); - Node* const result = CallCFunction6( - type_intptr, type_ptr, type_ptr, type_intptr, type_ptr, type_intptr, - type_intptr, function_addr, isolate_ptr, subject_ptr, subject_length, - search_ptr, search_length, start_position); + Node* const result = CallCFunction( + function_addr, type_intptr, std::make_pair(type_ptr, isolate_ptr), + std::make_pair(type_ptr, subject_ptr), + std::make_pair(type_intptr, subject_length), + std::make_pair(type_ptr, search_ptr), + std::make_pair(type_intptr, search_length), + std::make_pair(type_intptr, start_position)); return result; } @@ -321,7 +324,7 @@ TF_BUILTIN(SubString, StringBuiltinsAssembler) { } void StringBuiltinsAssembler::GenerateStringAt( - char const* method_name, TNode<Context> context, Node* receiver, + char const* method_name, TNode<Context> context, TNode<Object> receiver, TNode<Object> maybe_position, TNode<Object> default_return, const StringAtAccessor& accessor) { // Check that {receiver} is coercible to Object and convert it to a String. @@ -707,7 +710,7 @@ TF_BUILTIN(StringFromCharCode, CodeStubAssembler) { // ES6 #sec-string.prototype.charat TF_BUILTIN(StringPrototypeCharAt, StringBuiltinsAssembler) { TNode<Context> context = CAST(Parameter(Descriptor::kContext)); - Node* receiver = Parameter(Descriptor::kReceiver); + TNode<Object> receiver = CAST(Parameter(Descriptor::kReceiver)); TNode<Object> maybe_position = CAST(Parameter(Descriptor::kPosition)); GenerateStringAt("String.prototype.charAt", context, receiver, maybe_position, @@ -722,7 +725,7 @@ TF_BUILTIN(StringPrototypeCharAt, StringBuiltinsAssembler) { // ES6 #sec-string.prototype.charcodeat TF_BUILTIN(StringPrototypeCharCodeAt, StringBuiltinsAssembler) { TNode<Context> context = CAST(Parameter(Descriptor::kContext)); - Node* receiver = Parameter(Descriptor::kReceiver); + TNode<Object> receiver = CAST(Parameter(Descriptor::kReceiver)); TNode<Object> maybe_position = CAST(Parameter(Descriptor::kPosition)); GenerateStringAt("String.prototype.charCodeAt", context, receiver, @@ -737,7 +740,7 @@ TF_BUILTIN(StringPrototypeCharCodeAt, StringBuiltinsAssembler) { // ES6 #sec-string.prototype.codepointat TF_BUILTIN(StringPrototypeCodePointAt, StringBuiltinsAssembler) { TNode<Context> context = CAST(Parameter(Descriptor::kContext)); - Node* receiver = Parameter(Descriptor::kReceiver); + TNode<Object> receiver = CAST(Parameter(Descriptor::kReceiver)); TNode<Object> maybe_position = CAST(Parameter(Descriptor::kPosition)); GenerateStringAt("String.prototype.codePointAt", context, receiver, @@ -760,8 +763,8 @@ TF_BUILTIN(StringPrototypeConcat, CodeStubAssembler) { CodeStubArguments arguments( this, ChangeInt32ToIntPtr(Parameter(Descriptor::kJSActualArgumentsCount))); - Node* receiver = arguments.GetReceiver(); - Node* context = Parameter(Descriptor::kContext); + TNode<Object> receiver = arguments.GetReceiver(); + TNode<Context> context = CAST(Parameter(Descriptor::kContext)); // Check that {receiver} is coercible to Object and convert it to a String. receiver = ToThisString(context, receiver, "String.prototype.concat"); @@ -867,9 +870,10 @@ void StringBuiltinsAssembler::StringIndexOf( Node* const memchr = ExternalConstant(ExternalReference::libc_memchr_function()); Node* const result_address = - CallCFunction3(MachineType::Pointer(), MachineType::Pointer(), - MachineType::IntPtr(), MachineType::UintPtr(), memchr, - string_addr, search_byte, search_length); + CallCFunction(memchr, MachineType::Pointer(), + std::make_pair(MachineType::Pointer(), string_addr), + std::make_pair(MachineType::IntPtr(), search_byte), + std::make_pair(MachineType::UintPtr(), search_length)); GotoIf(WordEqual(result_address, int_zero), &return_minus_1); Node* const result_index = IntPtrAdd(IntPtrSub(result_address, string_addr), start_position); @@ -1160,121 +1164,6 @@ compiler::Node* StringBuiltinsAssembler::GetSubstitution( return var_result.value(); } -// ES6 #sec-string.prototype.repeat -TF_BUILTIN(StringPrototypeRepeat, StringBuiltinsAssembler) { - Label invalid_count(this), invalid_string_length(this), - return_emptystring(this); - - TNode<Context> context = CAST(Parameter(Descriptor::kContext)); - Node* const receiver = Parameter(Descriptor::kReceiver); - TNode<Object> count = CAST(Parameter(Descriptor::kCount)); - Node* const string = - ToThisString(context, receiver, "String.prototype.repeat"); - - VARIABLE( - var_count, MachineRepresentation::kTagged, - ToInteger_Inline(context, count, CodeStubAssembler::kTruncateMinusZero)); - - // Verifies a valid count and takes a fast path when the result will be an - // empty string. - { - Label if_count_isheapnumber(this, Label::kDeferred); - - GotoIfNot(TaggedIsSmi(var_count.value()), &if_count_isheapnumber); - { - // If count is a SMI, throw a RangeError if less than 0 or greater than - // the maximum string length. - TNode<Smi> smi_count = CAST(var_count.value()); - GotoIf(SmiLessThan(smi_count, SmiConstant(0)), &invalid_count); - GotoIf(SmiEqual(smi_count, SmiConstant(0)), &return_emptystring); - GotoIf(Word32Equal(LoadStringLengthAsWord32(string), Int32Constant(0)), - &return_emptystring); - GotoIf(SmiGreaterThan(smi_count, SmiConstant(String::kMaxLength)), - &invalid_string_length); - Return(CallBuiltin(Builtins::kStringRepeat, context, string, smi_count)); - } - - // If count is a Heap Number... - // 1) If count is Infinity, throw a RangeError exception - // 2) If receiver is an empty string, return an empty string - // 3) Otherwise, throw RangeError exception - BIND(&if_count_isheapnumber); - { - CSA_ASSERT(this, IsNumberNormalized(var_count.value())); - Node* const number_value = LoadHeapNumberValue(var_count.value()); - GotoIf(Float64Equal(number_value, Float64Constant(V8_INFINITY)), - &invalid_count); - GotoIf(Float64LessThan(number_value, Float64Constant(0.0)), - &invalid_count); - Branch(Word32Equal(LoadStringLengthAsWord32(string), Int32Constant(0)), - &return_emptystring, &invalid_string_length); - } - } - - BIND(&return_emptystring); - Return(EmptyStringConstant()); - - BIND(&invalid_count); - { - ThrowRangeError(context, MessageTemplate::kInvalidCountValue, - var_count.value()); - } - - BIND(&invalid_string_length); - { - CallRuntime(Runtime::kThrowInvalidStringLength, context); - Unreachable(); - } -} - -// Helper with less checks -TF_BUILTIN(StringRepeat, StringBuiltinsAssembler) { - Node* const context = Parameter(Descriptor::kContext); - Node* const string = Parameter(Descriptor::kString); - TNode<Smi> const count = CAST(Parameter(Descriptor::kCount)); - - CSA_ASSERT(this, IsString(string)); - CSA_ASSERT(this, Word32BinaryNot(IsEmptyString(string))); - CSA_ASSERT(this, TaggedIsPositiveSmi(count)); - - // The string is repeated with the following algorithm: - // let n = count; - // let power_of_two_repeats = string; - // let result = ""; - // while (true) { - // if (n & 1) result += s; - // n >>= 1; - // if (n === 0) return result; - // power_of_two_repeats += power_of_two_repeats; - // } - VARIABLE(var_result, MachineRepresentation::kTagged, EmptyStringConstant()); - VARIABLE(var_temp, MachineRepresentation::kTagged, string); - TVARIABLE(Smi, var_count, count); - - Label loop(this, {&var_count, &var_result, &var_temp}), return_result(this); - Goto(&loop); - BIND(&loop); - { - { - Label next(this); - GotoIfNot(SmiToInt32(SmiAnd(var_count.value(), SmiConstant(1))), &next); - var_result.Bind(CallBuiltin(Builtins::kStringAdd_CheckNone, context, - var_result.value(), var_temp.value())); - Goto(&next); - BIND(&next); - } - - var_count = SmiShr(var_count.value(), 1); - GotoIf(SmiEqual(var_count.value(), SmiConstant(0)), &return_result); - var_temp.Bind(CallBuiltin(Builtins::kStringAdd_CheckNone, context, - var_temp.value(), var_temp.value())); - Goto(&loop); - } - - BIND(&return_result); - Return(var_result.value()); -} - // ES6 #sec-string.prototype.replace TF_BUILTIN(StringPrototypeReplace, StringBuiltinsAssembler) { Label out(this); @@ -1570,8 +1459,9 @@ class StringPadAssembler : public StringBuiltinsAssembler { void Generate(Variant variant, const char* method_name, TNode<IntPtrT> argc, TNode<Context> context) { CodeStubArguments arguments(this, argc); - Node* const receiver = arguments.GetReceiver(); - Node* const receiver_string = ToThisString(context, receiver, method_name); + TNode<Object> receiver = arguments.GetReceiver(); + TNode<String> receiver_string = + ToThisString(context, receiver, method_name); TNode<Smi> const string_length = LoadStringLengthAsSmi(receiver_string); TVARIABLE(String, var_fill_string, StringConstant(" ")); @@ -1939,7 +1829,7 @@ TF_BUILTIN(StringPrototypeSubstr, StringBuiltinsAssembler) { ChangeInt32ToIntPtr(Parameter(Descriptor::kJSActualArgumentsCount)); CodeStubArguments args(this, argc); - Node* const receiver = args.GetReceiver(); + TNode<Object> receiver = args.GetReceiver(); TNode<Object> start = args.GetOptionalArgumentValue(kStartArg); TNode<Object> length = args.GetOptionalArgumentValue(kLengthArg); TNode<Context> context = CAST(Parameter(Descriptor::kContext)); @@ -2095,10 +1985,10 @@ TF_BUILTIN(StringPrototypeSubstring, StringBuiltinsAssembler) { ChangeInt32ToIntPtr(Parameter(Descriptor::kJSActualArgumentsCount)); CodeStubArguments args(this, argc); - Node* const receiver = args.GetReceiver(); - Node* const start = args.GetOptionalArgumentValue(kStartArg); - Node* const end = args.GetOptionalArgumentValue(kEndArg); - Node* const context = Parameter(Descriptor::kContext); + TNode<Object> receiver = args.GetReceiver(); + TNode<Object> start = args.GetOptionalArgumentValue(kStartArg); + TNode<Object> end = args.GetOptionalArgumentValue(kEndArg); + TNode<Context> context = CAST(Parameter(Descriptor::kContext)); Label out(this); @@ -2174,7 +2064,7 @@ void StringTrimAssembler::Generate(String::TrimMode mode, Label return_emptystring(this), if_runtime(this); CodeStubArguments arguments(this, argc); - Node* const receiver = arguments.GetReceiver(); + TNode<Object> receiver = arguments.GetReceiver(); // Check that {receiver} is coercible to Object and convert it to a String. TNode<String> const string = ToThisString(context, receiver, method_name); @@ -2332,8 +2222,8 @@ TF_BUILTIN(StringPrototypeValueOf, CodeStubAssembler) { } TF_BUILTIN(StringPrototypeIterator, CodeStubAssembler) { - Node* context = Parameter(Descriptor::kContext); - Node* receiver = Parameter(Descriptor::kReceiver); + TNode<Context> context = CAST(Parameter(Descriptor::kContext)); + TNode<Object> receiver = CAST(Parameter(Descriptor::kReceiver)); Node* string = ToThisString(context, receiver, "String.prototype[Symbol.iterator]"); @@ -2548,154 +2438,5 @@ TF_BUILTIN(StringToList, StringBuiltinsAssembler) { Return(StringToList(context, string)); } -// ----------------------------------------------------------------------------- -// ES6 section B.2.3 Additional Properties of the String.prototype object - -class StringHtmlAssembler : public StringBuiltinsAssembler { - public: - explicit StringHtmlAssembler(compiler::CodeAssemblerState* state) - : StringBuiltinsAssembler(state) {} - - protected: - void Generate(Node* const context, Node* const receiver, - const char* method_name, const char* tag_name) { - Node* const string = ToThisString(context, receiver, method_name); - std::string open_tag = "<" + std::string(tag_name) + ">"; - std::string close_tag = "</" + std::string(tag_name) + ">"; - - Node* strings[] = {StringConstant(open_tag.c_str()), string, - StringConstant(close_tag.c_str())}; - Return(ConcatStrings(context, strings, arraysize(strings))); - } - - void GenerateWithAttribute(Node* const context, Node* const receiver, - const char* method_name, const char* tag_name, - const char* attr, Node* const value) { - Node* const string = ToThisString(context, receiver, method_name); - TNode<String> value_string = - EscapeQuotes(CAST(context), ToString_Inline(context, value)); - std::string open_tag_attr = - "<" + std::string(tag_name) + " " + std::string(attr) + "=\""; - std::string close_tag = "</" + std::string(tag_name) + ">"; - - Node* strings[] = {StringConstant(open_tag_attr.c_str()), value_string, - StringConstant("\">"), string, - StringConstant(close_tag.c_str())}; - Return(ConcatStrings(context, strings, arraysize(strings))); - } - - Node* ConcatStrings(Node* const context, Node** strings, int len) { - VARIABLE(var_result, MachineRepresentation::kTagged, strings[0]); - for (int i = 1; i < len; i++) { - var_result.Bind(CallStub(CodeFactory::StringAdd(isolate()), context, - var_result.value(), strings[i])); - } - return var_result.value(); - } - - TNode<String> EscapeQuotes(TNode<Context> context, TNode<String> string) { - return CAST(CallRuntime(Runtime::kStringEscapeQuotes, context, string)); - } -}; - -// ES6 #sec-string.prototype.anchor -TF_BUILTIN(StringPrototypeAnchor, StringHtmlAssembler) { - Node* const context = Parameter(Descriptor::kContext); - Node* const receiver = Parameter(Descriptor::kReceiver); - Node* const value = Parameter(Descriptor::kValue); - GenerateWithAttribute(context, receiver, "String.prototype.anchor", "a", - "name", value); -} - -// ES6 #sec-string.prototype.big -TF_BUILTIN(StringPrototypeBig, StringHtmlAssembler) { - Node* const context = Parameter(Descriptor::kContext); - Node* const receiver = Parameter(Descriptor::kReceiver); - Generate(context, receiver, "String.prototype.big", "big"); -} - -// ES6 #sec-string.prototype.blink -TF_BUILTIN(StringPrototypeBlink, StringHtmlAssembler) { - Node* const context = Parameter(Descriptor::kContext); - Node* const receiver = Parameter(Descriptor::kReceiver); - Generate(context, receiver, "String.prototype.blink", "blink"); -} - -// ES6 #sec-string.prototype.bold -TF_BUILTIN(StringPrototypeBold, StringHtmlAssembler) { - Node* const context = Parameter(Descriptor::kContext); - Node* const receiver = Parameter(Descriptor::kReceiver); - Generate(context, receiver, "String.prototype.bold", "b"); -} - -// ES6 #sec-string.prototype.fontcolor -TF_BUILTIN(StringPrototypeFontcolor, StringHtmlAssembler) { - Node* const context = Parameter(Descriptor::kContext); - Node* const receiver = Parameter(Descriptor::kReceiver); - Node* const value = Parameter(Descriptor::kValue); - GenerateWithAttribute(context, receiver, "String.prototype.fontcolor", "font", - "color", value); -} - -// ES6 #sec-string.prototype.fontsize -TF_BUILTIN(StringPrototypeFontsize, StringHtmlAssembler) { - Node* const context = Parameter(Descriptor::kContext); - Node* const receiver = Parameter(Descriptor::kReceiver); - Node* const value = Parameter(Descriptor::kValue); - GenerateWithAttribute(context, receiver, "String.prototype.fontsize", "font", - "size", value); -} - -// ES6 #sec-string.prototype.fixed -TF_BUILTIN(StringPrototypeFixed, StringHtmlAssembler) { - Node* const context = Parameter(Descriptor::kContext); - Node* const receiver = Parameter(Descriptor::kReceiver); - Generate(context, receiver, "String.prototype.fixed", "tt"); -} - -// ES6 #sec-string.prototype.italics -TF_BUILTIN(StringPrototypeItalics, StringHtmlAssembler) { - Node* const context = Parameter(Descriptor::kContext); - Node* const receiver = Parameter(Descriptor::kReceiver); - Generate(context, receiver, "String.prototype.italics", "i"); -} - -// ES6 #sec-string.prototype.link -TF_BUILTIN(StringPrototypeLink, StringHtmlAssembler) { - Node* const context = Parameter(Descriptor::kContext); - Node* const receiver = Parameter(Descriptor::kReceiver); - Node* const value = Parameter(Descriptor::kValue); - GenerateWithAttribute(context, receiver, "String.prototype.link", "a", "href", - value); -} - -// ES6 #sec-string.prototype.small -TF_BUILTIN(StringPrototypeSmall, StringHtmlAssembler) { - Node* const context = Parameter(Descriptor::kContext); - Node* const receiver = Parameter(Descriptor::kReceiver); - Generate(context, receiver, "String.prototype.small", "small"); -} - -// ES6 #sec-string.prototype.strike -TF_BUILTIN(StringPrototypeStrike, StringHtmlAssembler) { - Node* const context = Parameter(Descriptor::kContext); - Node* const receiver = Parameter(Descriptor::kReceiver); - Generate(context, receiver, "String.prototype.strike", "strike"); -} - -// ES6 #sec-string.prototype.sub -TF_BUILTIN(StringPrototypeSub, StringHtmlAssembler) { - Node* const context = Parameter(Descriptor::kContext); - Node* const receiver = Parameter(Descriptor::kReceiver); - Generate(context, receiver, "String.prototype.sub", "sub"); -} - -// ES6 #sec-string.prototype.sup -TF_BUILTIN(StringPrototypeSup, StringHtmlAssembler) { - Node* const context = Parameter(Descriptor::kContext); - Node* const receiver = Parameter(Descriptor::kReceiver); - Generate(context, receiver, "String.prototype.sup", "sup"); -} - } // namespace internal } // namespace v8 diff --git a/deps/v8/src/builtins/builtins-string-gen.h b/deps/v8/src/builtins/builtins-string-gen.h index 863a008549..9485d40011 100644 --- a/deps/v8/src/builtins/builtins-string-gen.h +++ b/deps/v8/src/builtins/builtins-string-gen.h @@ -68,7 +68,7 @@ class StringBuiltinsAssembler : public CodeStubAssembler { StringAtAccessor; void GenerateStringAt(const char* method_name, TNode<Context> context, - Node* receiver, TNode<Object> maybe_position, + TNode<Object> receiver, TNode<Object> maybe_position, TNode<Object> default_return, const StringAtAccessor& accessor); @@ -134,8 +134,8 @@ class StringTrimAssembler : public StringBuiltinsAssembler { explicit StringTrimAssembler(compiler::CodeAssemblerState* state) : StringBuiltinsAssembler(state) {} - void GotoIfNotWhiteSpaceOrLineTerminator(Node* const char_code, - Label* const if_not_whitespace); + V8_EXPORT_PRIVATE void GotoIfNotWhiteSpaceOrLineTerminator( + Node* const char_code, Label* const if_not_whitespace); protected: void Generate(String::TrimMode mode, const char* method, TNode<IntPtrT> argc, diff --git a/deps/v8/src/builtins/builtins-typed-array-gen.cc b/deps/v8/src/builtins/builtins-typed-array-gen.cc index 75ff1de59f..1206785526 100644 --- a/deps/v8/src/builtins/builtins-typed-array-gen.cc +++ b/deps/v8/src/builtins/builtins-typed-array-gen.cc @@ -495,9 +495,10 @@ void TypedArrayBuiltinsAssembler::CallCMemmove(TNode<RawPtrT> dest_ptr, TNode<UintPtrT> byte_length) { TNode<ExternalReference> memmove = ExternalConstant(ExternalReference::libc_memmove_function()); - CallCFunction3(MachineType::AnyTagged(), MachineType::Pointer(), - MachineType::Pointer(), MachineType::UintPtr(), memmove, - dest_ptr, src_ptr, byte_length); + CallCFunction(memmove, MachineType::AnyTagged(), + std::make_pair(MachineType::Pointer(), dest_ptr), + std::make_pair(MachineType::Pointer(), src_ptr), + std::make_pair(MachineType::UintPtr(), byte_length)); } void TypedArrayBuiltinsAssembler::CallCMemcpy(TNode<RawPtrT> dest_ptr, @@ -505,9 +506,10 @@ void TypedArrayBuiltinsAssembler::CallCMemcpy(TNode<RawPtrT> dest_ptr, TNode<UintPtrT> byte_length) { TNode<ExternalReference> memcpy = ExternalConstant(ExternalReference::libc_memcpy_function()); - CallCFunction3(MachineType::AnyTagged(), MachineType::Pointer(), - MachineType::Pointer(), MachineType::UintPtr(), memcpy, - dest_ptr, src_ptr, byte_length); + CallCFunction(memcpy, MachineType::AnyTagged(), + std::make_pair(MachineType::Pointer(), dest_ptr), + std::make_pair(MachineType::Pointer(), src_ptr), + std::make_pair(MachineType::UintPtr(), byte_length)); } void TypedArrayBuiltinsAssembler::CallCMemset(TNode<RawPtrT> dest_ptr, @@ -515,9 +517,10 @@ void TypedArrayBuiltinsAssembler::CallCMemset(TNode<RawPtrT> dest_ptr, TNode<UintPtrT> length) { TNode<ExternalReference> memset = ExternalConstant(ExternalReference::libc_memset_function()); - CallCFunction3(MachineType::AnyTagged(), MachineType::Pointer(), - MachineType::IntPtr(), MachineType::UintPtr(), memset, - dest_ptr, value, length); + CallCFunction(memset, MachineType::AnyTagged(), + std::make_pair(MachineType::Pointer(), dest_ptr), + std::make_pair(MachineType::IntPtr(), value), + std::make_pair(MachineType::UintPtr(), length)); } void TypedArrayBuiltinsAssembler:: @@ -530,10 +533,12 @@ void TypedArrayBuiltinsAssembler:: Word32BinaryNot(IsBigInt64ElementsKind(LoadElementsKind(dest)))); TNode<ExternalReference> f = ExternalConstant( ExternalReference::copy_fast_number_jsarray_elements_to_typed_array()); - CallCFunction5(MachineType::AnyTagged(), MachineType::AnyTagged(), - MachineType::AnyTagged(), MachineType::AnyTagged(), - MachineType::UintPtr(), MachineType::UintPtr(), f, context, - source, dest, source_length, offset); + CallCFunction(f, MachineType::AnyTagged(), + std::make_pair(MachineType::AnyTagged(), context), + std::make_pair(MachineType::AnyTagged(), source), + std::make_pair(MachineType::AnyTagged(), dest), + std::make_pair(MachineType::UintPtr(), source_length), + std::make_pair(MachineType::UintPtr(), offset)); } void TypedArrayBuiltinsAssembler::CallCCopyTypedArrayElementsToTypedArray( @@ -541,10 +546,11 @@ void TypedArrayBuiltinsAssembler::CallCCopyTypedArrayElementsToTypedArray( TNode<IntPtrT> source_length, TNode<IntPtrT> offset) { TNode<ExternalReference> f = ExternalConstant( ExternalReference::copy_typed_array_elements_to_typed_array()); - CallCFunction4(MachineType::AnyTagged(), MachineType::AnyTagged(), - MachineType::AnyTagged(), MachineType::UintPtr(), - MachineType::UintPtr(), f, source, dest, source_length, - offset); + CallCFunction(f, MachineType::AnyTagged(), + std::make_pair(MachineType::AnyTagged(), source), + std::make_pair(MachineType::AnyTagged(), dest), + std::make_pair(MachineType::UintPtr(), source_length), + std::make_pair(MachineType::UintPtr(), offset)); } void TypedArrayBuiltinsAssembler::CallCCopyTypedArrayElementsSlice( @@ -552,9 +558,11 @@ void TypedArrayBuiltinsAssembler::CallCCopyTypedArrayElementsSlice( TNode<IntPtrT> end) { TNode<ExternalReference> f = ExternalConstant(ExternalReference::copy_typed_array_elements_slice()); - CallCFunction4(MachineType::AnyTagged(), MachineType::AnyTagged(), - MachineType::AnyTagged(), MachineType::UintPtr(), - MachineType::UintPtr(), f, source, dest, start, end); + CallCFunction(f, MachineType::AnyTagged(), + std::make_pair(MachineType::AnyTagged(), source), + std::make_pair(MachineType::AnyTagged(), dest), + std::make_pair(MachineType::UintPtr(), start), + std::make_pair(MachineType::UintPtr(), end)); } void TypedArrayBuiltinsAssembler::DispatchTypedArrayByElementsKind( diff --git a/deps/v8/src/builtins/builtins-utils.h b/deps/v8/src/builtins/builtins-utils.h index 283c521067..ebae29ea42 100644 --- a/deps/v8/src/builtins/builtins-utils.h +++ b/deps/v8/src/builtins/builtins-utils.h @@ -83,7 +83,7 @@ class BuiltinArguments : public Arguments { V8_WARN_UNUSED_RESULT Address Builtin_##name( \ int args_length, Address* args_object, Isolate* isolate) { \ DCHECK(isolate->context().is_null() || isolate->context()->IsContext()); \ - if (V8_UNLIKELY(FLAG_runtime_stats)) { \ + if (V8_UNLIKELY(TracingFlags::is_runtime_stats_enabled())) { \ return Builtin_Impl_Stats_##name(args_length, args_object, isolate); \ } \ BuiltinArguments args(args_length, args_object); \ diff --git a/deps/v8/src/builtins/builtins-wasm-gen.cc b/deps/v8/src/builtins/builtins-wasm-gen.cc index 382a835b49..373e9dbfef 100644 --- a/deps/v8/src/builtins/builtins-wasm-gen.cc +++ b/deps/v8/src/builtins/builtins-wasm-gen.cc @@ -105,7 +105,7 @@ TF_BUILTIN(WasmThrow, WasmBuiltinsAssembler) { TailCallRuntimeWithCEntry(Runtime::kThrow, centry, context, exception); } -TF_BUILTIN(WasmAtomicWake, WasmBuiltinsAssembler) { +TF_BUILTIN(WasmAtomicNotify, WasmBuiltinsAssembler) { TNode<Uint32T> address = UncheckedCast<Uint32T>(Parameter(Descriptor::kAddress)); TNode<Uint32T> count = UncheckedCast<Uint32T>(Parameter(Descriptor::kCount)); @@ -125,7 +125,7 @@ TF_BUILTIN(WasmAtomicWake, WasmBuiltinsAssembler) { StoreHeapNumberValue(count_heap, ChangeUint32ToFloat64(count)); TNode<Smi> result_smi = UncheckedCast<Smi>(CallRuntimeWithCEntry( - Runtime::kWasmAtomicWake, centry, NoContextConstant(), instance, + Runtime::kWasmAtomicNotify, centry, NoContextConstant(), instance, address_heap, count_heap)); ReturnRaw(SmiToInt32(result_smi)); } @@ -226,7 +226,59 @@ TF_BUILTIN(WasmMemoryGrow, WasmBuiltinsAssembler) { ReturnRaw(Int32Constant(-1)); } -TF_BUILTIN(BigIntToWasmI64, WasmBuiltinsAssembler) { +TF_BUILTIN(WasmTableGet, WasmBuiltinsAssembler) { + TNode<Int32T> entry_index = + UncheckedCast<Int32T>(Parameter(Descriptor::kEntryIndex)); + TNode<Object> instance = LoadInstanceFromFrame(); + TNode<Code> centry = LoadCEntryFromInstance(instance); + TNode<Object> context = LoadContextFromInstance(instance); + Label entry_index_out_of_range(this, Label::kDeferred); + + TNode<BoolT> entry_index_fits_in_smi = + IsValidPositiveSmi(ChangeInt32ToIntPtr(entry_index)); + GotoIfNot(entry_index_fits_in_smi, &entry_index_out_of_range); + + TNode<Smi> entry_index_smi = SmiFromInt32(entry_index); + TNode<Smi> table_index_smi = + UncheckedCast<Smi>(Parameter(Descriptor::kTableIndex)); + + TailCallRuntimeWithCEntry(Runtime::kWasmFunctionTableGet, centry, context, + instance, table_index_smi, entry_index_smi); + + BIND(&entry_index_out_of_range); + MessageTemplate message_id = + wasm::WasmOpcodes::TrapReasonToMessageId(wasm::kTrapTableOutOfBounds); + TailCallRuntimeWithCEntry(Runtime::kThrowWasmError, centry, context, + SmiConstant(static_cast<int>(message_id))); +} + +TF_BUILTIN(WasmTableSet, WasmBuiltinsAssembler) { + TNode<Int32T> entry_index = + UncheckedCast<Int32T>(Parameter(Descriptor::kEntryIndex)); + TNode<Object> instance = LoadInstanceFromFrame(); + TNode<Code> centry = LoadCEntryFromInstance(instance); + TNode<Object> context = LoadContextFromInstance(instance); + Label entry_index_out_of_range(this, Label::kDeferred); + + TNode<BoolT> entry_index_fits_in_smi = + IsValidPositiveSmi(ChangeInt32ToIntPtr(entry_index)); + GotoIfNot(entry_index_fits_in_smi, &entry_index_out_of_range); + + TNode<Smi> entry_index_smi = SmiFromInt32(entry_index); + TNode<Smi> table_index_smi = + UncheckedCast<Smi>(Parameter(Descriptor::kTableIndex)); + TNode<Object> value = UncheckedCast<Object>(Parameter(Descriptor::kValue)); + TailCallRuntimeWithCEntry(Runtime::kWasmFunctionTableSet, centry, context, + instance, table_index_smi, entry_index_smi, value); + + BIND(&entry_index_out_of_range); + MessageTemplate message_id = + wasm::WasmOpcodes::TrapReasonToMessageId(wasm::kTrapTableOutOfBounds); + TailCallRuntimeWithCEntry(Runtime::kThrowWasmError, centry, context, + SmiConstant(static_cast<int>(message_id))); +} + +TF_BUILTIN(WasmI64ToBigInt, WasmBuiltinsAssembler) { if (!Is64()) { Unreachable(); return; @@ -236,8 +288,7 @@ TF_BUILTIN(BigIntToWasmI64, WasmBuiltinsAssembler) { TNode<IntPtrT> argument = UncheckedCast<IntPtrT>(Parameter(Descriptor::kArgument)); - TailCallStub(BigIntToWasmI64Descriptor(), target, NoContextConstant(), - argument); + TailCallStub(I64ToBigIntDescriptor(), target, NoContextConstant(), argument); } TF_BUILTIN(WasmBigIntToI64, WasmBuiltinsAssembler) { diff --git a/deps/v8/src/builtins/builtins.cc b/deps/v8/src/builtins/builtins.cc index 129beb2700..4eee41febd 100644 --- a/deps/v8/src/builtins/builtins.cc +++ b/deps/v8/src/builtins/builtins.cc @@ -311,8 +311,8 @@ Handle<ByteArray> Builtins::GenerateOffHeapTrampolineRelocInfo( // generated instruction stream. CodeDesc desc = generator.Generate(kNullAddress); - Handle<ByteArray> reloc_info = - isolate->factory()->NewByteArray(desc.reloc_size, TENURED_READ_ONLY); + Handle<ByteArray> reloc_info = isolate->factory()->NewByteArray( + desc.reloc_size, AllocationType::kReadOnly); Code::CopyRelocInfoToByteArray(*reloc_info, desc); return reloc_info; diff --git a/deps/v8/src/builtins/builtins.h b/deps/v8/src/builtins/builtins.h index 7ea440e004..e077bc1b15 100644 --- a/deps/v8/src/builtins/builtins.h +++ b/deps/v8/src/builtins/builtins.h @@ -81,7 +81,7 @@ class Builtins { // Used by CreateOffHeapTrampolines in isolate.cc. void set_builtin(int index, Code builtin); - Code builtin(int index); + V8_EXPORT_PRIVATE Code builtin(int index); V8_EXPORT_PRIVATE Handle<Code> builtin_handle(int index); V8_EXPORT_PRIVATE static Callable CallableFor(Isolate* isolate, Name name); diff --git a/deps/v8/src/builtins/collections.tq b/deps/v8/src/builtins/collections.tq index 48b2048275..8cf9f3b90d 100644 --- a/deps/v8/src/builtins/collections.tq +++ b/deps/v8/src/builtins/collections.tq @@ -14,18 +14,18 @@ namespace collections { typeswitch (a.elements) { case (elements: FixedArray): { return KeyValuePair{ - length > 0 ? array::LoadElementOrUndefined(elements, 0) : - Undefined, - length > 1 ? array::LoadElementOrUndefined(elements, 1) : - Undefined + key: length > 0 ? array::LoadElementOrUndefined(elements, 0) : + Undefined, + value: length > 1 ? array::LoadElementOrUndefined(elements, 1) : + Undefined }; } case (elements: FixedDoubleArray): { return KeyValuePair{ - length > 0 ? array::LoadElementOrUndefined(elements, 0) : - Undefined, - length > 1 ? array::LoadElementOrUndefined(elements, 1) : - Undefined + key: length > 0 ? array::LoadElementOrUndefined(elements, 0) : + Undefined, + value: length > 1 ? array::LoadElementOrUndefined(elements, 1) : + Undefined }; } case (Object): deferred { @@ -49,8 +49,8 @@ namespace collections { } label Generic { return KeyValuePair{ - GetProperty(o, Convert<Smi>(0)), - GetProperty(o, Convert<Smi>(1)) + key: GetProperty(o, Convert<Smi>(0)), + value: GetProperty(o, Convert<Smi>(1)) }; } } diff --git a/deps/v8/src/builtins/constants-table-builder.cc b/deps/v8/src/builtins/constants-table-builder.cc index 5aacf2ef75..6c779e74f6 100644 --- a/deps/v8/src/builtins/constants-table-builder.cc +++ b/deps/v8/src/builtins/constants-table-builder.cc @@ -36,7 +36,7 @@ uint32_t BuiltinsConstantsTableBuilder::AddObject(Handle<Object> object) { isolate_->heap()->builtins_constants_table()); // Must be on the main thread. - DCHECK(ThreadId::Current().Equals(isolate_->thread_id())); + DCHECK_EQ(ThreadId::Current(), isolate_->thread_id()); // Must be generating embedded builtin code. DCHECK(isolate_->IsGeneratingEmbeddedBuiltins()); @@ -94,7 +94,7 @@ void BuiltinsConstantsTableBuilder::Finalize() { if (map_.size() == 0) return; Handle<FixedArray> table = - isolate_->factory()->NewFixedArray(map_.size(), TENURED); + isolate_->factory()->NewFixedArray(map_.size(), AllocationType::kOld); Builtins* builtins = isolate_->builtins(); ConstantsMap::IteratableScope it_scope(&map_); diff --git a/deps/v8/src/builtins/data-view.tq b/deps/v8/src/builtins/data-view.tq index e90da0ad1b..383be19a9d 100644 --- a/deps/v8/src/builtins/data-view.tq +++ b/deps/v8/src/builtins/data-view.tq @@ -382,7 +382,7 @@ namespace data_view { extern macro DataViewBuiltinsAssembler::DataViewElementSize( constexpr ElementsKind): constexpr int31; - macro DataViewGet( + transitioning macro DataViewGet( context: Context, receiver: Object, offset: Object, requestedLittleEndian: Object, kind: constexpr ElementsKind): Numeric { let dataView: JSDataView = @@ -441,19 +441,19 @@ namespace data_view { } } - javascript builtin DataViewPrototypeGetUint8( + transitioning javascript builtin DataViewPrototypeGetUint8( context: Context, receiver: Object, ...arguments): Object { let offset: Object = arguments.length > 0 ? arguments[0] : Undefined; return DataViewGet(context, receiver, offset, Undefined, UINT8_ELEMENTS); } - javascript builtin DataViewPrototypeGetInt8( + transitioning javascript builtin DataViewPrototypeGetInt8( context: Context, receiver: Object, ...arguments): Object { let offset: Object = arguments.length > 0 ? arguments[0] : Undefined; return DataViewGet(context, receiver, offset, Undefined, INT8_ELEMENTS); } - javascript builtin DataViewPrototypeGetUint16( + transitioning javascript builtin DataViewPrototypeGetUint16( context: Context, receiver: Object, ...arguments): Object { let offset: Object = arguments.length > 0 ? arguments[0] : Undefined; let isLittleEndian: Object = @@ -462,7 +462,7 @@ namespace data_view { context, receiver, offset, isLittleEndian, UINT16_ELEMENTS); } - javascript builtin DataViewPrototypeGetInt16( + transitioning javascript builtin DataViewPrototypeGetInt16( context: Context, receiver: Object, ...arguments): Object { let offset: Object = arguments.length > 0 ? arguments[0] : Undefined; let isLittleEndian: Object = @@ -471,7 +471,7 @@ namespace data_view { context, receiver, offset, isLittleEndian, INT16_ELEMENTS); } - javascript builtin DataViewPrototypeGetUint32( + transitioning javascript builtin DataViewPrototypeGetUint32( context: Context, receiver: Object, ...arguments): Object { let offset: Object = arguments.length > 0 ? arguments[0] : Undefined; let isLittleEndian: Object = @@ -480,7 +480,7 @@ namespace data_view { context, receiver, offset, isLittleEndian, UINT32_ELEMENTS); } - javascript builtin DataViewPrototypeGetInt32( + transitioning javascript builtin DataViewPrototypeGetInt32( context: Context, receiver: Object, ...arguments): Object { let offset: Object = arguments.length > 0 ? arguments[0] : Undefined; let isLittleEndian: Object = @@ -489,7 +489,7 @@ namespace data_view { context, receiver, offset, isLittleEndian, INT32_ELEMENTS); } - javascript builtin DataViewPrototypeGetFloat32( + transitioning javascript builtin DataViewPrototypeGetFloat32( context: Context, receiver: Object, ...arguments): Object { let offset: Object = arguments.length > 0 ? arguments[0] : Undefined; let isLittleEndian: Object = @@ -498,7 +498,7 @@ namespace data_view { context, receiver, offset, isLittleEndian, FLOAT32_ELEMENTS); } - javascript builtin DataViewPrototypeGetFloat64( + transitioning javascript builtin DataViewPrototypeGetFloat64( context: Context, receiver: Object, ...arguments): Object { let offset: Object = arguments.length > 0 ? arguments[0] : Undefined; let isLittleEndian: Object = @@ -507,7 +507,7 @@ namespace data_view { context, receiver, offset, isLittleEndian, FLOAT64_ELEMENTS); } - javascript builtin DataViewPrototypeGetBigUint64( + transitioning javascript builtin DataViewPrototypeGetBigUint64( context: Context, receiver: Object, ...arguments): Object { let offset: Object = arguments.length > 0 ? arguments[0] : Undefined; let isLittleEndian: Object = @@ -516,7 +516,7 @@ namespace data_view { context, receiver, offset, isLittleEndian, BIGUINT64_ELEMENTS); } - javascript builtin DataViewPrototypeGetBigInt64( + transitioning javascript builtin DataViewPrototypeGetBigInt64( context: Context, receiver: Object, ...arguments): Object { let offset: Object = arguments.length > 0 ? arguments[0] : Undefined; let isLittleEndian: Object = @@ -659,7 +659,7 @@ namespace data_view { StoreDataView64(buffer, offset, lowWord, highWord, requestedLittleEndian); } - macro DataViewSet( + transitioning macro DataViewSet( context: Context, receiver: Object, offset: Object, value: Object, requestedLittleEndian: Object, kind: constexpr ElementsKind): Object { let dataView: JSDataView = @@ -745,7 +745,7 @@ namespace data_view { return Undefined; } - javascript builtin DataViewPrototypeSetUint8( + transitioning javascript builtin DataViewPrototypeSetUint8( context: Context, receiver: Object, ...arguments): Object { let offset: Object = arguments.length > 0 ? arguments[0] : Undefined; let value: Object = arguments.length > 1 ? arguments[1] : Undefined; @@ -753,7 +753,7 @@ namespace data_view { context, receiver, offset, value, Undefined, UINT8_ELEMENTS); } - javascript builtin DataViewPrototypeSetInt8( + transitioning javascript builtin DataViewPrototypeSetInt8( context: Context, receiver: Object, ...arguments): Object { let offset: Object = arguments.length > 0 ? arguments[0] : Undefined; let value: Object = arguments.length > 1 ? arguments[1] : Undefined; @@ -761,7 +761,7 @@ namespace data_view { context, receiver, offset, value, Undefined, INT8_ELEMENTS); } - javascript builtin DataViewPrototypeSetUint16( + transitioning javascript builtin DataViewPrototypeSetUint16( context: Context, receiver: Object, ...arguments): Object { let offset: Object = arguments.length > 0 ? arguments[0] : Undefined; let value: Object = arguments.length > 1 ? arguments[1] : Undefined; @@ -771,7 +771,7 @@ namespace data_view { context, receiver, offset, value, isLittleEndian, UINT16_ELEMENTS); } - javascript builtin DataViewPrototypeSetInt16( + transitioning javascript builtin DataViewPrototypeSetInt16( context: Context, receiver: Object, ...arguments): Object { let offset: Object = arguments.length > 0 ? arguments[0] : Undefined; let value: Object = arguments.length > 1 ? arguments[1] : Undefined; @@ -781,7 +781,7 @@ namespace data_view { context, receiver, offset, value, isLittleEndian, INT16_ELEMENTS); } - javascript builtin DataViewPrototypeSetUint32( + transitioning javascript builtin DataViewPrototypeSetUint32( context: Context, receiver: Object, ...arguments): Object { let offset: Object = arguments.length > 0 ? arguments[0] : Undefined; let value: Object = arguments.length > 1 ? arguments[1] : Undefined; @@ -791,7 +791,7 @@ namespace data_view { context, receiver, offset, value, isLittleEndian, UINT32_ELEMENTS); } - javascript builtin DataViewPrototypeSetInt32( + transitioning javascript builtin DataViewPrototypeSetInt32( context: Context, receiver: Object, ...arguments): Object { let offset: Object = arguments.length > 0 ? arguments[0] : Undefined; let value: Object = arguments.length > 1 ? arguments[1] : Undefined; @@ -801,7 +801,7 @@ namespace data_view { context, receiver, offset, value, isLittleEndian, INT32_ELEMENTS); } - javascript builtin DataViewPrototypeSetFloat32( + transitioning javascript builtin DataViewPrototypeSetFloat32( context: Context, receiver: Object, ...arguments): Object { let offset: Object = arguments.length > 0 ? arguments[0] : Undefined; let value: Object = arguments.length > 1 ? arguments[1] : Undefined; @@ -811,7 +811,7 @@ namespace data_view { context, receiver, offset, value, isLittleEndian, FLOAT32_ELEMENTS); } - javascript builtin DataViewPrototypeSetFloat64( + transitioning javascript builtin DataViewPrototypeSetFloat64( context: Context, receiver: Object, ...arguments): Object { let offset: Object = arguments.length > 0 ? arguments[0] : Undefined; let value: Object = arguments.length > 1 ? arguments[1] : Undefined; @@ -821,7 +821,7 @@ namespace data_view { context, receiver, offset, value, isLittleEndian, FLOAT64_ELEMENTS); } - javascript builtin DataViewPrototypeSetBigUint64( + transitioning javascript builtin DataViewPrototypeSetBigUint64( context: Context, receiver: Object, ...arguments): Object { let offset: Object = arguments.length > 0 ? arguments[0] : Undefined; let value: Object = arguments.length > 1 ? arguments[1] : Undefined; @@ -831,7 +831,7 @@ namespace data_view { context, receiver, offset, value, isLittleEndian, BIGUINT64_ELEMENTS); } - javascript builtin DataViewPrototypeSetBigInt64( + transitioning javascript builtin DataViewPrototypeSetBigInt64( context: Context, receiver: Object, ...arguments): Object { let offset: Object = arguments.length > 0 ? arguments[0] : Undefined; let value: Object = arguments.length > 1 ? arguments[1] : Undefined; diff --git a/deps/v8/src/builtins/frames.tq b/deps/v8/src/builtins/frames.tq index 960fa9f68c..6113e41f91 100644 --- a/deps/v8/src/builtins/frames.tq +++ b/deps/v8/src/builtins/frames.tq @@ -33,7 +33,8 @@ type FrameBase extends RawPtr constexpr 'void*'; type StandardFrame extends FrameBase constexpr 'void*'; type ArgumentsAdaptorFrame extends FrameBase constexpr 'void*'; type StubFrame extends FrameBase constexpr 'void*'; -type Frame = ArgumentsAdaptorFrame | StandardFrame | StubFrame; +type FrameWithArguments = StandardFrame | ArgumentsAdaptorFrame; +type Frame = FrameWithArguments | StubFrame; extern macro LoadFramePointer(): Frame; extern macro LoadParentFramePointer(): Frame; diff --git a/deps/v8/src/builtins/growable-fixed-array.tq b/deps/v8/src/builtins/growable-fixed-array.tq index eb62e56c98..a11e3e6cbd 100644 --- a/deps/v8/src/builtins/growable-fixed-array.tq +++ b/deps/v8/src/builtins/growable-fixed-array.tq @@ -40,6 +40,6 @@ namespace growable_fixed_array { } macro NewGrowableFixedArray(): GrowableFixedArray { - return GrowableFixedArray{kEmptyFixedArray, 0, 0}; + return GrowableFixedArray{array: kEmptyFixedArray, capacity: 0, length: 0}; } } diff --git a/deps/v8/src/builtins/ia32/builtins-ia32.cc b/deps/v8/src/builtins/ia32/builtins-ia32.cc index fa72ec2278..40a37b6a9f 100644 --- a/deps/v8/src/builtins/ia32/builtins-ia32.cc +++ b/deps/v8/src/builtins/ia32/builtins-ia32.cc @@ -47,15 +47,11 @@ void Builtins::Generate_Adaptor(MacroAssembler* masm, Address address, static void GenerateTailCallToReturnedCode(MacroAssembler* masm, Runtime::FunctionId function_id) { // ----------- S t a t e ------------- - // -- eax : argument count (preserved for callee) // -- edx : new target (preserved for callee) // -- edi : target function (preserved for callee) // ----------------------------------- { FrameScope scope(masm, StackFrame::INTERNAL); - // Push the number of arguments to the callee. - __ SmiTag(eax); - __ push(eax); // Push a copy of the target function and the new target. __ push(edi); __ push(edx); @@ -68,8 +64,6 @@ static void GenerateTailCallToReturnedCode(MacroAssembler* masm, // Restore target function and new target. __ pop(edx); __ pop(edi); - __ pop(eax); - __ SmiUntag(eax); } static_assert(kJavaScriptCallCodeStartRegister == ecx, "ABI mismatch"); @@ -78,6 +72,30 @@ static void GenerateTailCallToReturnedCode(MacroAssembler* masm, namespace { +void Generate_StackOverflowCheck(MacroAssembler* masm, Register num_args, + Register scratch, Label* stack_overflow, + bool include_receiver = false) { + // Check the stack for overflow. We are not trying to catch + // interruptions (e.g. debug break and preemption) here, so the "real stack + // limit" is checked. + ExternalReference real_stack_limit = + ExternalReference::address_of_real_stack_limit(masm->isolate()); + // Compute the space that is left as a negative number in scratch. If + // we already overflowed, this will be a positive number. + __ mov(scratch, __ ExternalReferenceAsOperand(real_stack_limit, scratch)); + __ sub(scratch, esp); + // Add the size of the arguments. + static_assert(kSystemPointerSize == 4, + "The next instruction assumes kSystemPointerSize == 4"); + __ lea(scratch, Operand(scratch, num_args, times_system_pointer_size, 0)); + if (include_receiver) { + __ add(scratch, Immediate(kSystemPointerSize)); + } + // See if we overflowed, i.e. scratch is positive. + __ cmp(scratch, Immediate(0)); + __ j(greater, stack_overflow); // Signed comparison. +} + void Generate_JSBuiltinsConstructStubHelper(MacroAssembler* masm) { // ----------- S t a t e ------------- // -- eax: number of arguments @@ -86,6 +104,10 @@ void Generate_JSBuiltinsConstructStubHelper(MacroAssembler* masm) { // -- esi: context // ----------------------------------- + Label stack_overflow; + + Generate_StackOverflowCheck(masm, eax, ecx, &stack_overflow); + // Enter a construct frame. { FrameScope scope(masm, StackFrame::CONSTRUCT); @@ -145,30 +167,13 @@ void Generate_JSBuiltinsConstructStubHelper(MacroAssembler* masm) { 1 * kSystemPointerSize)); // 1 ~ receiver __ PushReturnAddressFrom(ecx); __ ret(0); -} -void Generate_StackOverflowCheck(MacroAssembler* masm, Register num_args, - Register scratch, Label* stack_overflow, - bool include_receiver = false) { - // Check the stack for overflow. We are not trying to catch - // interruptions (e.g. debug break and preemption) here, so the "real stack - // limit" is checked. - ExternalReference real_stack_limit = - ExternalReference::address_of_real_stack_limit(masm->isolate()); - // Compute the space that is left as a negative number in scratch. If - // we already overflowed, this will be a positive number. - __ mov(scratch, __ ExternalReferenceAsOperand(real_stack_limit, scratch)); - __ sub(scratch, esp); - // Add the size of the arguments. - static_assert(kSystemPointerSize == 4, - "The next instruction assumes kSystemPointerSize == 4"); - __ lea(scratch, Operand(scratch, num_args, times_system_pointer_size, 0)); - if (include_receiver) { - __ add(scratch, Immediate(kSystemPointerSize)); + __ bind(&stack_overflow); + { + FrameScope scope(masm, StackFrame::INTERNAL); + __ CallRuntime(Runtime::kThrowStackOverflow); + __ int3(); // This should be unreachable. } - // See if we overflowed, i.e. scratch is positive. - __ cmp(scratch, Immediate(0)); - __ j(greater, stack_overflow); // Signed comparison. } } // namespace @@ -790,12 +795,11 @@ static void TailCallRuntimeIfMarkerEquals(MacroAssembler* masm, static void MaybeTailCallOptimizedCodeSlot(MacroAssembler* masm, Register scratch) { // ----------- S t a t e ------------- - // -- eax : argument count (preserved for callee if needed, and caller) // -- edx : new target (preserved for callee if needed, and caller) // -- edi : target function (preserved for callee if needed, and caller) // -- ecx : feedback vector (also used as scratch, value is not preserved) // ----------------------------------- - DCHECK(!AreAliased(eax, edx, edi, scratch)); + DCHECK(!AreAliased(edx, edi, scratch)); Label optimized_code_slot_is_weak_ref, fallthrough; @@ -854,7 +858,6 @@ static void MaybeTailCallOptimizedCodeSlot(MacroAssembler* masm, __ LoadWeakValue(optimized_code_entry, &fallthrough); - __ push(eax); __ push(edx); // Check if the optimized code is marked for deopt. If it is, bailout to a @@ -873,14 +876,12 @@ static void MaybeTailCallOptimizedCodeSlot(MacroAssembler* masm, static_assert(kJavaScriptCallCodeStartRegister == ecx, "ABI mismatch"); __ LoadCodeObjectEntry(ecx, optimized_code_entry); __ pop(edx); - __ pop(eax); __ jmp(ecx); // Optimized code slot contains deoptimized code, evict it and re-enter the // closure's code. __ bind(&found_deoptimized_code); __ pop(edx); - __ pop(eax); GenerateTailCallToReturnedCode(masm, Runtime::kEvictOptimizedCodeSlot); } @@ -983,7 +984,9 @@ void Builtins::Generate_InterpreterEntryTrampoline(MacroAssembler* masm) { __ mov(feedback_vector, FieldOperand(closure, JSFunction::kFeedbackCellOffset)); __ mov(feedback_vector, FieldOperand(feedback_vector, Cell::kValueOffset)); - __ JumpIfRoot(feedback_vector, RootIndex::kUndefinedValue, &push_stack_frame); + __ mov(eax, FieldOperand(feedback_vector, HeapObject::kMapOffset)); + __ CmpInstanceType(eax, FEEDBACK_VECTOR_TYPE); + __ j(not_equal, &push_stack_frame); // Read off the optimized code slot in the closure's feedback vector, and if // there is optimized code or an optimization marker, call that instead. @@ -1022,10 +1025,15 @@ void Builtins::Generate_InterpreterEntryTrampoline(MacroAssembler* masm) { AbortReason::kFunctionDataShouldBeBytecodeArrayOnInterpreterEntry); } - // Reset code age. - __ mov_b(FieldOperand(kInterpreterBytecodeArrayRegister, - BytecodeArray::kBytecodeAgeOffset), - Immediate(BytecodeArray::kNoAgeBytecodeAge)); + // Reset code age and the OSR arming. The OSR field and BytecodeAgeOffset are + // 8-bit fields next to each other, so we could just optimize by writing a + // 16-bit. These static asserts guard our assumption is valid. + STATIC_ASSERT(BytecodeArray::kBytecodeAgeOffset == + BytecodeArray::kOSRNestingLevelOffset + kCharSize); + STATIC_ASSERT(BytecodeArray::kNoAgeBytecodeAge == 0); + __ mov_w(FieldOperand(kInterpreterBytecodeArrayRegister, + BytecodeArray::kOSRNestingLevelOffset), + Immediate(0)); // Push bytecode array. __ push(kInterpreterBytecodeArrayRegister); diff --git a/deps/v8/src/builtins/mips/OWNERS b/deps/v8/src/builtins/mips/OWNERS index b455d9ef29..cab3679d65 100644 --- a/deps/v8/src/builtins/mips/OWNERS +++ b/deps/v8/src/builtins/mips/OWNERS @@ -1,3 +1 @@ -arikalo@wavecomp.com -prudic@wavecomp.com -skovacevic@wavecomp.com +xwafish@gmail.com diff --git a/deps/v8/src/builtins/mips/builtins-mips.cc b/deps/v8/src/builtins/mips/builtins-mips.cc index a840875874..00ae715719 100644 --- a/deps/v8/src/builtins/mips/builtins-mips.cc +++ b/deps/v8/src/builtins/mips/builtins-mips.cc @@ -2943,32 +2943,27 @@ void CallApiFunctionAndReturn(MacroAssembler* masm, Register function_address, void Builtins::Generate_CallApiCallback(MacroAssembler* masm) { // ----------- S t a t e ------------- - // -- cp : kTargetContext - // -- a1 : kApiFunctionAddress - // -- a2 : kArgc + // -- cp : context + // -- a1 : api function address + // -- a2 : arguments count (not including the receiver) + // -- a3 : call data + // -- a0 : holder // -- // -- sp[0] : last argument // -- ... // -- sp[(argc - 1) * 4] : first argument // -- sp[(argc + 0) * 4] : receiver - // -- sp[(argc + 1) * 4] : kHolder - // -- sp[(argc + 2) * 4] : kCallData // ----------------------------------- Register api_function_address = a1; Register argc = a2; + Register call_data = a3; + Register holder = a0; Register scratch = t0; Register base = t1; // For addressing MemOperands on the stack. - DCHECK(!AreAliased(api_function_address, argc, scratch, base)); - - // Stack offsets (without argc). - static constexpr int kReceiverOffset = 0 * kPointerSize; - static constexpr int kHolderOffset = kReceiverOffset + kPointerSize; - static constexpr int kCallDataOffset = kHolderOffset + kPointerSize; - - // Extra stack arguments are: the receiver, kHolder, kCallData. - static constexpr int kExtraStackArgumentCount = 3; + DCHECK(!AreAliased(api_function_address, argc, call_data, + holder, scratch, base)); typedef FunctionCallbackArguments FCA; @@ -2998,22 +2993,22 @@ void Builtins::Generate_CallApiCallback(MacroAssembler* masm) { __ Subu(sp, sp, Operand(FCA::kArgsLength * kPointerSize)); // kHolder. - __ lw(scratch, MemOperand(base, kHolderOffset)); - __ sw(scratch, MemOperand(sp, 0 * kPointerSize)); + __ sw(holder, MemOperand(sp, 0 * kPointerSize)); // kIsolate. __ li(scratch, ExternalReference::isolate_address(masm->isolate())); __ sw(scratch, MemOperand(sp, 1 * kPointerSize)); - // kReturnValueDefaultValue, kReturnValue, and kNewTarget. + // kReturnValueDefaultValue and kReturnValue. __ LoadRoot(scratch, RootIndex::kUndefinedValue); __ sw(scratch, MemOperand(sp, 2 * kPointerSize)); __ sw(scratch, MemOperand(sp, 3 * kPointerSize)); - __ sw(scratch, MemOperand(sp, 5 * kPointerSize)); // kData. - __ lw(scratch, MemOperand(base, kCallDataOffset)); - __ sw(scratch, MemOperand(sp, 4 * kPointerSize)); + __ sw(call_data, MemOperand(sp, 4 * kPointerSize)); + + // kNewTarget. + __ sw(scratch, MemOperand(sp, 5 * kPointerSize)); // Keep a pointer to kHolder (= implicit_args) in a scratch register. // We use it below to set up the FunctionCallbackInfo object. @@ -3042,7 +3037,7 @@ void Builtins::Generate_CallApiCallback(MacroAssembler* masm) { // from the API function here. // Note: Unlike on other architectures, this stores the number of slots to // drop, not the number of bytes. - __ Addu(scratch, argc, Operand(FCA::kArgsLength + kExtraStackArgumentCount)); + __ Addu(scratch, argc, Operand(FCA::kArgsLength + 1 /* receiver */)); __ sw(scratch, MemOperand(sp, 4 * kPointerSize)); // v8::InvocationCallback's argument. diff --git a/deps/v8/src/builtins/mips64/OWNERS b/deps/v8/src/builtins/mips64/OWNERS index b455d9ef29..cab3679d65 100644 --- a/deps/v8/src/builtins/mips64/OWNERS +++ b/deps/v8/src/builtins/mips64/OWNERS @@ -1,3 +1 @@ -arikalo@wavecomp.com -prudic@wavecomp.com -skovacevic@wavecomp.com +xwafish@gmail.com diff --git a/deps/v8/src/builtins/mips64/builtins-mips64.cc b/deps/v8/src/builtins/mips64/builtins-mips64.cc index ee0e5238b8..bba01d5668 100644 --- a/deps/v8/src/builtins/mips64/builtins-mips64.cc +++ b/deps/v8/src/builtins/mips64/builtins-mips64.cc @@ -2979,32 +2979,27 @@ void CallApiFunctionAndReturn(MacroAssembler* masm, Register function_address, void Builtins::Generate_CallApiCallback(MacroAssembler* masm) { // ----------- S t a t e ------------- - // -- cp : kTargetContext - // -- a1 : kApiFunctionAddress - // -- a2 : kArgc + // -- cp : context + // -- a1 : api function address + // -- a2 : arguments count (not including the receiver) + // -- a3 : call data + // -- a0 : holder // -- // -- sp[0] : last argument // -- ... // -- sp[(argc - 1) * 8] : first argument // -- sp[(argc + 0) * 8] : receiver - // -- sp[(argc + 1) * 8] : kHolder - // -- sp[(argc + 2) * 8] : kCallData // ----------------------------------- Register api_function_address = a1; Register argc = a2; + Register call_data = a3; + Register holder = a0; Register scratch = t0; Register base = t1; // For addressing MemOperands on the stack. - DCHECK(!AreAliased(api_function_address, argc, scratch, base)); - - // Stack offsets (without argc). - static constexpr int kReceiverOffset = 0 * kPointerSize; - static constexpr int kHolderOffset = kReceiverOffset + kPointerSize; - static constexpr int kCallDataOffset = kHolderOffset + kPointerSize; - - // Extra stack arguments are: the receiver, kHolder, kCallData. - static constexpr int kExtraStackArgumentCount = 3; + DCHECK(!AreAliased(api_function_address, argc, call_data, + holder, scratch, base)); typedef FunctionCallbackArguments FCA; @@ -3034,22 +3029,22 @@ void Builtins::Generate_CallApiCallback(MacroAssembler* masm) { __ Dsubu(sp, sp, Operand(FCA::kArgsLength * kPointerSize)); // kHolder. - __ Ld(scratch, MemOperand(base, kHolderOffset)); - __ Sd(scratch, MemOperand(sp, 0 * kPointerSize)); + __ Sd(holder, MemOperand(sp, 0 * kPointerSize)); // kIsolate. __ li(scratch, ExternalReference::isolate_address(masm->isolate())); __ Sd(scratch, MemOperand(sp, 1 * kPointerSize)); - // kReturnValueDefaultValue, kReturnValue, and kNewTarget. + // kReturnValueDefaultValue and kReturnValue. __ LoadRoot(scratch, RootIndex::kUndefinedValue); __ Sd(scratch, MemOperand(sp, 2 * kPointerSize)); __ Sd(scratch, MemOperand(sp, 3 * kPointerSize)); - __ Sd(scratch, MemOperand(sp, 5 * kPointerSize)); // kData. - __ Ld(scratch, MemOperand(base, kCallDataOffset)); - __ Sd(scratch, MemOperand(sp, 4 * kPointerSize)); + __ Sd(call_data, MemOperand(sp, 4 * kPointerSize)); + + // kNewTarget. + __ Sd(scratch, MemOperand(sp, 5 * kPointerSize)); // Keep a pointer to kHolder (= implicit_args) in a scratch register. // We use it below to set up the FunctionCallbackInfo object. @@ -3082,7 +3077,7 @@ void Builtins::Generate_CallApiCallback(MacroAssembler* masm) { // from the API function here. // Note: Unlike on other architectures, this stores the number of slots to // drop, not the number of bytes. - __ Daddu(scratch, argc, Operand(FCA::kArgsLength + kExtraStackArgumentCount)); + __ Daddu(scratch, argc, Operand(FCA::kArgsLength + 1 /* receiver */)); __ Sd(scratch, MemOperand(sp, 4 * kPointerSize)); // v8::InvocationCallback's argument. diff --git a/deps/v8/src/builtins/ppc/builtins-ppc.cc b/deps/v8/src/builtins/ppc/builtins-ppc.cc index 36254a6776..f089f086af 100644 --- a/deps/v8/src/builtins/ppc/builtins-ppc.cc +++ b/deps/v8/src/builtins/ppc/builtins-ppc.cc @@ -1101,11 +1101,17 @@ void Builtins::Generate_InterpreterEntryTrampoline(MacroAssembler* masm) { FrameScope frame_scope(masm, StackFrame::MANUAL); __ PushStandardFrame(closure); - // Reset code age. - __ mov(r8, Operand(BytecodeArray::kNoAgeBytecodeAge)); - __ StoreByte(r8, FieldMemOperand(kInterpreterBytecodeArrayRegister, - BytecodeArray::kBytecodeAgeOffset), - r0); + // Reset code age and the OSR arming. The OSR field and BytecodeAgeOffset are + // 8-bit fields next to each other, so we could just optimize by writing a + // 16-bit. These static asserts guard our assumption is valid. + STATIC_ASSERT(BytecodeArray::kBytecodeAgeOffset == + BytecodeArray::kOSRNestingLevelOffset + kCharSize); + STATIC_ASSERT(BytecodeArray::kNoAgeBytecodeAge == 0); + __ li(r8, Operand(0)); + __ StoreHalfWord(r8, + FieldMemOperand(kInterpreterBytecodeArrayRegister, + BytecodeArray::kOSRNestingLevelOffset), + r0); // Load initial bytecode offset. __ mov(kInterpreterBytecodeOffsetRegister, @@ -3272,8 +3278,21 @@ void Builtins::Generate_CallApiGetter(MacroAssembler* masm) { } void Builtins::Generate_DirectCEntry(MacroAssembler* masm) { - // Unused. - __ stop(0); + // Place the return address on the stack, making the call + // GC safe. The RegExp backend also relies on this. + __ mflr(r0); + __ StoreP(r0, MemOperand(sp, kStackFrameExtraParamSlot * kPointerSize)); + + if (ABI_USES_FUNCTION_DESCRIPTORS && FLAG_embedded_builtins) { + // AIX/PPC64BE Linux use a function descriptor; + __ LoadP(ToRegister(ABI_TOC_REGISTER), MemOperand(ip, kPointerSize)); + __ LoadP(ip, MemOperand(ip, 0)); // Instruction address + } + + __ Call(ip); // Call the C++ function. + __ LoadP(r0, MemOperand(sp, kStackFrameExtraParamSlot * kPointerSize)); + __ mtlr(r0); + __ blr(); } #undef __ diff --git a/deps/v8/src/builtins/proxy-constructor.tq b/deps/v8/src/builtins/proxy-constructor.tq new file mode 100644 index 0000000000..178759b595 --- /dev/null +++ b/deps/v8/src/builtins/proxy-constructor.tq @@ -0,0 +1,63 @@ +// 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-proxy-gen.h' + +namespace proxy { + + extern macro ProxiesCodeStubAssembler::GetProxyConstructorJSNewTarget(): + Object; + + // ES #sec-proxy-constructor + // https://tc39.github.io/ecma262/#sec-proxy-constructor + transitioning javascript builtin + ProxyConstructor(implicit context: Context)( + receiver: Object, target: Object, handler: Object): JSProxy { + try { + // 1. If NewTarget is undefined, throw a TypeError exception. + const newTarget: Object = GetProxyConstructorJSNewTarget(); + if (newTarget == Undefined) { + ThrowTypeError(kConstructorNotFunction, 'Proxy'); + } + + // 2. Return ? ProxyCreate(target, handler). + // https://tc39.github.io/ecma262/#sec-proxycreate + // 1. If Type(target) is not Object, throw a TypeError exception. + // 2. If target is a Proxy exotic object and target.[[ProxyHandler]] is + // null, throw a TypeError exception. + // 3. If Type(handler) is not Object, throw a TypeError exception. + // 4. If handler is a Proxy exotic object and handler.[[ProxyHandler]] + // is null, throw a TypeError exception. + const targetJSReceiver = + Cast<JSReceiver>(target) otherwise ThrowProxyNonObject; + if (IsRevokedProxy(targetJSReceiver)) { + goto ThrowProxyHandlerOrTargetRevoked; + } + + const handlerJSReceiver = + Cast<JSReceiver>(handler) otherwise ThrowProxyNonObject; + if (IsRevokedProxy(handlerJSReceiver)) { + goto ThrowProxyHandlerOrTargetRevoked; + } + + // 5. Let P be a newly created object. + // 6. Set P's essential internal methods (except for [[Call]] and + // [[Construct]]) to the definitions specified in 9.5. + // 7. If IsCallable(target) is true, then + // a. Set P.[[Call]] as specified in 9.5.12. + // b. If IsConstructor(target) is true, then + // 1. Set P.[[Construct]] as specified in 9.5.13. + // 8. Set P.[[ProxyTarget]] to target. + // 9. Set P.[[ProxyHandler]] to handler. + // 10. Return P. + return AllocateProxy(targetJSReceiver, handlerJSReceiver); + } + label ThrowProxyNonObject deferred { + ThrowTypeError(kProxyNonObject); + } + label ThrowProxyHandlerOrTargetRevoked deferred { + ThrowTypeError(kProxyHandlerOrTargetRevoked); + } + } +} diff --git a/deps/v8/src/builtins/proxy-revocable.tq b/deps/v8/src/builtins/proxy-revocable.tq new file mode 100644 index 0000000000..695f005c9b --- /dev/null +++ b/deps/v8/src/builtins/proxy-revocable.tq @@ -0,0 +1,57 @@ +// 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-proxy-gen.h' + +namespace proxy { + + extern macro ProxiesCodeStubAssembler::AllocateProxyRevokeFunction( + Object, Object): JSFunction; + macro AllocateProxyRevokeFunction(implicit context: Context)(proxy: JSProxy): + JSFunction { + return AllocateProxyRevokeFunction(proxy, context); + } + + // Proxy.revocable(target, handler) + // https://tc39.github.io/ecma262/#sec-proxy.revocable + transitioning javascript builtin + ProxyRevocable( + context: Context, receiver: Object, target: Object, + handler: Object): JSProxyRevocableResult { + try { + const targetJSReceiver = + Cast<JSReceiver>(target) otherwise ThrowProxyNonObject; + if (IsRevokedProxy(targetJSReceiver)) { + goto ThrowProxyHandlerOrTargetRevoked; + } + + const handlerJSReceiver = + Cast<JSReceiver>(handler) otherwise ThrowProxyNonObject; + if (IsRevokedProxy(handlerJSReceiver)) { + goto ThrowProxyHandlerOrTargetRevoked; + } + + // 1. Let p be ? ProxyCreate(target, handler). + const proxy: JSProxy = AllocateProxy(targetJSReceiver, handlerJSReceiver); + + // 2. Let steps be the algorithm steps defined in Proxy Revocation + // Functions. + // 3. Let revoker be CreateBuiltinFunction(steps, « [[RevocableProxy]] »). + // 4. Set revoker.[[RevocableProxy]] to p. + const revoke: JSFunction = AllocateProxyRevokeFunction(proxy); + + // 5. Let result be ObjectCreate(%ObjectPrototype%). + // 6. Perform CreateDataProperty(result, "proxy", p). + // 7. Perform CreateDataProperty(result, "revoke", revoker). + // 8. Return result. + return NewJSProxyRevocableResult(proxy, revoke); + } + label ThrowProxyNonObject deferred { + ThrowTypeError(kProxyNonObject, 'Proxy.revocable'); + } + label ThrowProxyHandlerOrTargetRevoked deferred { + ThrowTypeError(kProxyHandlerOrTargetRevoked, 'Proxy.revocable'); + } + } +} diff --git a/deps/v8/src/builtins/proxy-revoke.tq b/deps/v8/src/builtins/proxy-revoke.tq new file mode 100644 index 0000000000..8ab5d8dd51 --- /dev/null +++ b/deps/v8/src/builtins/proxy-revoke.tq @@ -0,0 +1,37 @@ +// 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-proxy-gen.h' + +namespace proxy { + + // Proxy Revocation Functions + // https://tc39.github.io/ecma262/#sec-proxy-revocation-functions + // TODO(v8:9007) remove receiver in argument since we don't use it + transitioning javascript builtin + ProxyRevoke(context: Context, receiver: Object): Undefined { + // 1. Let p be F.[[RevocableProxy]]. + const proxyObject: Object = context[PROXY_SLOT]; + + // 2. If p is null, return undefined + if (proxyObject == Null) { + return Undefined; + } + + // 3. Set F.[[RevocableProxy]] to null. + context[PROXY_SLOT] = Null; + + // 4. Assert: p is a Proxy object. + const proxy: JSProxy = UnsafeCast<JSProxy>(proxyObject); + + // 5. Set p.[[ProxyTarget]] to null. + proxy.target = Null; + + // 6. Set p.[[ProxyHandler]] to null. + proxy.handler = Null; + + // 7. Return undefined. + return Undefined; + } +} diff --git a/deps/v8/src/builtins/proxy.tq b/deps/v8/src/builtins/proxy.tq new file mode 100644 index 0000000000..95e05be14f --- /dev/null +++ b/deps/v8/src/builtins/proxy.tq @@ -0,0 +1,22 @@ +// 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-proxy-gen.h' + +namespace proxy { + + extern macro ProxiesCodeStubAssembler::AllocateProxy( + JSReceiver, JSReceiver, Context): JSProxy; + macro AllocateProxy(implicit context: Context)( + target: JSReceiver, handler: JSReceiver): JSProxy { + return AllocateProxy(target, handler, context); + } + + macro IsRevokedProxy(implicit context: Context)(o: JSReceiver): bool { + const proxy: JSProxy = Cast<JSProxy>(o) otherwise return false; + const handler: JSReceiver = + Cast<JSReceiver>(proxy.handler) otherwise return true; + return false; + } +} diff --git a/deps/v8/src/builtins/regexp-replace.tq b/deps/v8/src/builtins/regexp-replace.tq new file mode 100644 index 0000000000..4b5d542b60 --- /dev/null +++ b/deps/v8/src/builtins/regexp-replace.tq @@ -0,0 +1,152 @@ +// 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-regexp-gen.h' + +namespace regexp_replace { + + extern builtin + StringIndexOf(implicit context: Context)(String, String, Smi): Smi; + extern builtin + SubString(implicit context: Context)(String, Smi, Smi): String; + + extern transitioning macro + RegExpBuiltinsAssembler::ReplaceGlobalCallableFastPath( + implicit context: Context)(JSRegExp, String, Callable): String; + extern macro + RegExpBuiltinsAssembler::AdvanceStringIndexFast(String, Number, bool): Smi; + + extern transitioning runtime + RegExpReplaceRT(Context, JSReceiver, String, Object): String; + extern transitioning runtime + StringReplaceNonGlobalRegExpWithFunction(implicit context: Context)( + String, JSRegExp, Callable): String; + + extern macro + RegExpBuiltinsAssembler::RegExpPrototypeExecBodyWithoutResultFast( + implicit context: Context)(JSReceiver, String): + RegExpMatchInfo labels IfDidNotMatch; + + transitioning macro RegExpReplaceFastString(implicit context: Context)( + regexp: FastJSRegExp, string: String, replaceString: String): String { + // The fast path is reached only if {receiver} is an unmodified JSRegExp + // instance, {replace_value} is non-callable, and ToString({replace_value}) + // does not contain '$', i.e. we're doing a simple string replacement. + let result: String = kEmptyString; + let lastMatchEnd: Smi = 0; + let unicode: bool = false; + let replaceLength: Smi = replaceString.length_smi; + const global: bool = regexp.global; + + if (global) { + unicode = regexp.unicode; + regexp.lastIndex = 0; + } + + while (true) { + const match: RegExpMatchInfo = RegExpPrototypeExecBodyWithoutResultFast( + regexp, string) otherwise break; + const matchStart: Smi = match.GetStartOfCapture(0); + const matchEnd: Smi = match.GetEndOfCapture(0); + + // TODO(jgruber): We could skip many of the checks that using SubString + // here entails. + result = result + SubString(string, lastMatchEnd, matchStart); + lastMatchEnd = matchEnd; + + if (replaceLength != 0) result = result + replaceString; + + // Non-global case ends here after the first replacement. + if (!global) break; + + // If match is the empty string, we have to increment lastIndex. + if (matchEnd == matchStart) { + regexp.lastIndex = + AdvanceStringIndexFast(string, regexp.lastIndex, unicode); + } + } + + return result + SubString(string, lastMatchEnd, string.length_smi); + } + + transitioning builtin RegExpReplace(implicit context: Context)( + regexp: FastJSRegExp, string: String, replaceValue: Object): String { + // TODO(pwong): Remove assert when all callers (StringPrototypeReplace) are + // from Torque. + assert(Is<FastJSRegExp>(regexp)); + + // 2. Is {replace_value} callable? + typeswitch (replaceValue) { + case (replaceFn: Callable): { + return regexp.global ? + ReplaceGlobalCallableFastPath(regexp, string, replaceFn) : + StringReplaceNonGlobalRegExpWithFunction(string, regexp, replaceFn); + } + case (Object): { + const stableRegexp: JSRegExp = regexp; + const replaceString: String = ToString_Inline(context, replaceValue); + + try { + // ToString(replaceValue) could potentially change the shape of the + // RegExp object. Recheck that we are still on the fast path and bail + // to runtime otherwise. + const fastRegexp = Cast<FastJSRegExp>(stableRegexp) otherwise Runtime; + if (StringIndexOf( + replaceString, SingleCharacterStringConstant('$'), 0) != -1) { + goto Runtime; + } + + return RegExpReplaceFastString(fastRegexp, string, replaceString); + } + label Runtime deferred { + return RegExpReplaceRT(context, stableRegexp, string, replaceString); + } + } + } + } + + transitioning javascript builtin RegExpPrototypeReplace( + context: Context, receiver: Object, ...arguments): Object { + const methodName: constexpr string = 'RegExp.prototype.@@replace'; + + // RegExpPrototypeReplace is a bit of a beast - a summary of dispatch logic: + // + // if (!IsFastRegExp(receiver)) CallRuntime(RegExpReplace) + // if (IsCallable(replace)) { + // if (IsGlobal(receiver)) { + // // Called 'fast-path' but contains several runtime calls. + // ReplaceGlobalCallableFastPath() + // } else { + // CallRuntime(StringReplaceNonGlobalRegExpWithFunction) + // } + // } else { + // if (replace.contains("$")) { + // CallRuntime(RegExpReplace) + // } else { + // ReplaceSimpleStringFastPath() + // } + // } + + const string: Object = arguments[0]; + const replaceValue: Object = arguments[1]; + + // Let rx be the this value. + // If Type(rx) is not Object, throw a TypeError exception. + const rx = Cast<JSReceiver>(receiver) + otherwise ThrowTypeError(kIncompatibleMethodReceiver, methodName); + + // Let S be ? ToString(string). + const s = ToString_Inline(context, string); + + // Fast-path checks: 1. Is the {receiver} an unmodified JSRegExp instance? + try { + const fastRx: FastJSRegExp = Cast<FastJSRegExp>(rx) otherwise Runtime; + return RegExpReplace(fastRx, s, replaceValue); + } + label Runtime deferred { + return RegExpReplaceRT(context, rx, s, replaceValue); + } + } + +} diff --git a/deps/v8/src/builtins/regexp.tq b/deps/v8/src/builtins/regexp.tq new file mode 100644 index 0000000000..a36e1a14eb --- /dev/null +++ b/deps/v8/src/builtins/regexp.tq @@ -0,0 +1,13 @@ +// 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-regexp-gen.h' + +namespace regexp { + + extern macro RegExpBuiltinsAssembler::BranchIfFastRegExp( + implicit context: Context)(HeapObject): never labels IsFast, + IsSlow; + +} diff --git a/deps/v8/src/builtins/s390/builtins-s390.cc b/deps/v8/src/builtins/s390/builtins-s390.cc index 3134a3f43e..b242e8921a 100644 --- a/deps/v8/src/builtins/s390/builtins-s390.cc +++ b/deps/v8/src/builtins/s390/builtins-s390.cc @@ -1152,11 +1152,17 @@ void Builtins::Generate_InterpreterEntryTrampoline(MacroAssembler* masm) { FrameScope frame_scope(masm, StackFrame::MANUAL); __ PushStandardFrame(closure); - // Reset code age. - __ mov(r1, Operand(BytecodeArray::kNoAgeBytecodeAge)); - __ StoreByte(r1, FieldMemOperand(kInterpreterBytecodeArrayRegister, - BytecodeArray::kBytecodeAgeOffset), - r0); + // Reset code age and the OSR arming. The OSR field and BytecodeAgeOffset are + // 8-bit fields next to each other, so we could just optimize by writing a + // 16-bit. These static asserts guard our assumption is valid. + STATIC_ASSERT(BytecodeArray::kBytecodeAgeOffset == + BytecodeArray::kOSRNestingLevelOffset + kCharSize); + STATIC_ASSERT(BytecodeArray::kNoAgeBytecodeAge == 0); + __ lghi(r1, Operand(0)); + __ StoreHalfWord(r1, + FieldMemOperand(kInterpreterBytecodeArrayRegister, + BytecodeArray::kOSRNestingLevelOffset), + r0); // Load the initial bytecode offset. __ mov(kInterpreterBytecodeOffsetRegister, diff --git a/deps/v8/src/builtins/setup-builtins-internal.cc b/deps/v8/src/builtins/setup-builtins-internal.cc index 23e03a705d..44f27f24f8 100644 --- a/deps/v8/src/builtins/setup-builtins-internal.cc +++ b/deps/v8/src/builtins/setup-builtins-internal.cc @@ -41,6 +41,7 @@ AssemblerOptions BuiltinAssemblerOptions(Isolate* isolate, AssemblerOptions options = AssemblerOptions::Default(isolate); CHECK(!options.isolate_independent_code); CHECK(!options.use_pc_relative_calls_and_jumps); + CHECK(!options.collect_win64_unwind_info); if (!isolate->IsGeneratingEmbeddedBuiltins() || !Builtins::IsIsolateIndependent(builtin_index)) { @@ -56,6 +57,7 @@ AssemblerOptions BuiltinAssemblerOptions(Isolate* isolate, options.isolate_independent_code = true; options.use_pc_relative_calls_and_jumps = pc_relative_calls_fit_in_code_range; + options.collect_win64_unwind_info = true; return options; } @@ -126,6 +128,9 @@ Code BuildWithMacroAssembler(Isolate* isolate, int32_t builtin_index, desc, Code::BUILTIN, masm.CodeObject(), builtin_index, MaybeHandle<ByteArray>(), DeoptimizationData::Empty(isolate), kMovable, kIsNotTurbofanned, kStackSlots); +#if defined(V8_OS_WIN_X64) + isolate->SetBuiltinUnwindData(builtin_index, masm.GetUnwindInfo()); +#endif PostBuildProfileAndTracing(isolate, *code, s_name); return *code; } diff --git a/deps/v8/src/builtins/string-html.tq b/deps/v8/src/builtins/string-html.tq new file mode 100644 index 0000000000..a2b1625206 --- /dev/null +++ b/deps/v8/src/builtins/string-html.tq @@ -0,0 +1,125 @@ +// 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. + +namespace string_html { + extern runtime StringEscapeQuotes(Context, String): String; + + // https://tc39.github.io/ecma262/#sec-createhtml + transitioning builtin CreateHTML(implicit context: Context)( + receiver: Object, methodName: String, tagName: String, attr: String, + attrValue: Object): String { + const tagContents: String = ToThisString(receiver, methodName); + let result = '<' + tagName; + if (attr != kEmptyString) { + const attrStringValue: String = + StringEscapeQuotes(context, ToString_Inline(context, attrValue)); + result = result + ' ' + attr + '=\"' + attrStringValue + '\"'; + } + + return result + '>' + tagContents + '</' + tagName + '>'; + } + + // https://tc39.github.io/ecma262/#sec-string.prototype.anchor + transitioning javascript builtin StringPrototypeAnchor( + context: Context, receiver: Object, ...arguments): String { + return CreateHTML( + receiver, 'String.prototype.anchor', 'a', 'name', arguments[0]); + } + + // https://tc39.github.io/ecma262/#sec-string.prototype.big + transitioning javascript builtin + StringPrototypeBig(context: Context, receiver: Object, ...arguments): String { + return CreateHTML( + receiver, 'String.prototype.big', 'big', kEmptyString, kEmptyString); + } + + // https://tc39.github.io/ecma262/#sec-string.prototype.blink + transitioning javascript builtin + StringPrototypeBlink(context: Context, receiver: Object, ...arguments): + String { + return CreateHTML( + receiver, 'String.prototype.blink', 'blink', kEmptyString, + kEmptyString); + } + + // https://tc39.github.io/ecma262/#sec-string.prototype.bold + transitioning javascript builtin + StringPrototypeBold(context: Context, receiver: Object, ...arguments): + String { + return CreateHTML( + receiver, 'String.prototype.bold', 'b', kEmptyString, kEmptyString); + } + + // https://tc39.github.io/ecma262/#sec-string.prototype.fontcolor + transitioning javascript builtin + StringPrototypeFontcolor(context: Context, receiver: Object, ...arguments): + String { + return CreateHTML( + receiver, 'String.prototype.fontcolor', 'font', 'color', arguments[0]); + } + + // https://tc39.github.io/ecma262/#sec-string.prototype.fontsize + transitioning javascript builtin + StringPrototypeFontsize(context: Context, receiver: Object, ...arguments): + String { + return CreateHTML( + receiver, 'String.prototype.fontsize', 'font', 'size', arguments[0]); + } + + // https://tc39.github.io/ecma262/#sec-string.prototype.fixed + transitioning javascript builtin + StringPrototypeFixed(context: Context, receiver: Object, ...arguments): + String { + return CreateHTML( + receiver, 'String.prototype.fixed', 'tt', kEmptyString, kEmptyString); + } + + // https://tc39.github.io/ecma262/#sec-string.prototype.italics + transitioning javascript builtin + StringPrototypeItalics(context: Context, receiver: Object, ...arguments): + String { + return CreateHTML( + receiver, 'String.prototype.italics', 'i', kEmptyString, kEmptyString); + } + + // https://tc39.github.io/ecma262/#sec-string.prototype.link + transitioning javascript builtin + StringPrototypeLink(context: Context, receiver: Object, ...arguments): + String { + return CreateHTML( + receiver, 'String.prototype.link', 'a', 'href', arguments[0]); + } + + // https://tc39.github.io/ecma262/#sec-string.prototype.small + transitioning javascript builtin + StringPrototypeSmall(context: Context, receiver: Object, ...arguments): + String { + return CreateHTML( + receiver, 'String.prototype.small', 'small', kEmptyString, + kEmptyString); + } + + // https://tc39.github.io/ecma262/#sec-string.prototype.strike + transitioning javascript builtin + StringPrototypeStrike(context: Context, receiver: Object, ...arguments): + String { + return CreateHTML( + receiver, 'String.prototype.strike', 'strike', kEmptyString, + kEmptyString); + } + + // https://tc39.github.io/ecma262/#sec-string.prototype.sub + transitioning javascript builtin + StringPrototypeSub(context: Context, receiver: Object, ...arguments): String { + return CreateHTML( + receiver, 'String.prototype.sub', 'sub', kEmptyString, kEmptyString); + } + + // https://tc39.github.io/ecma262/#sec-string.prototype.sup + transitioning javascript builtin + StringPrototypeSup(context: Context, receiver: Object, ...arguments): String { + return CreateHTML( + receiver, 'String.prototype.sup', 'sup', kEmptyString, kEmptyString); + } +} diff --git a/deps/v8/src/builtins/string-repeat.tq b/deps/v8/src/builtins/string-repeat.tq new file mode 100644 index 0000000000..f2590011ea --- /dev/null +++ b/deps/v8/src/builtins/string-repeat.tq @@ -0,0 +1,77 @@ +// 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. + +namespace string_repeat { + const kBuiltinName: constexpr string = 'String.prototype.repeat'; + + builtin StringRepeat(implicit context: Context)(string: String, count: Smi): + String { + assert(count >= 0); + assert(string != kEmptyString); + + let result: String = kEmptyString; + let powerOfTwoRepeats: String = string; + let n: intptr = Convert<intptr>(count); + + while (true) { + if ((n & 1) == 1) result = result + powerOfTwoRepeats; + + n = n >> 1; + if (n == 0) break; + + powerOfTwoRepeats = powerOfTwoRepeats + powerOfTwoRepeats; + } + + return result; + } + + // https://tc39.github.io/ecma262/#sec-string.prototype.repeat + transitioning javascript builtin StringPrototypeRepeat( + context: Context, receiver: Object, count: Object): String { + // 1. Let O be ? RequireObjectCoercible(this value). + // 2. Let S be ? ToString(O). + const s: String = ToThisString(receiver, kBuiltinName); + + try { + // 3. Let n be ? ToInteger(count). + typeswitch (ToInteger_Inline(context, count, kTruncateMinusZero)) { + case (n: Smi): { + // 4. If n < 0, throw a RangeError exception. + if (n < 0) goto InvalidCount; + + // 6. If n is 0, return the empty String. + if (n == 0 || s.length_uint32 == 0) goto EmptyString; + + if (n > kStringMaxLength) goto InvalidStringLength; + + // 7. Return the String value that is made from n copies of S appended + // together. + return StringRepeat(s, n); + } + case (heapNum: HeapNumber): deferred { + assert(IsNumberNormalized(heapNum)); + const n = LoadHeapNumberValue(heapNum); + + // 4. If n < 0, throw a RangeError exception. + // 5. If n is +∞, throw a RangeError exception. + if (n == V8_INFINITY || n < 0.0) goto InvalidCount; + + // 6. If n is 0, return the empty String. + if (s.length_uint32 == 0) goto EmptyString; + + goto InvalidStringLength; + } + } + } + label EmptyString { + return kEmptyString; + } + label InvalidCount deferred { + ThrowRangeError(kInvalidCountValue, count); + } + label InvalidStringLength deferred { + ThrowInvalidStringLength(context); + } + } +} diff --git a/deps/v8/src/builtins/typed-array-createtypedarray.tq b/deps/v8/src/builtins/typed-array-createtypedarray.tq index 04630dc295..31be407e52 100644 --- a/deps/v8/src/builtins/typed-array-createtypedarray.tq +++ b/deps/v8/src/builtins/typed-array-createtypedarray.tq @@ -172,7 +172,7 @@ namespace typed_array_createtypedarray { // 22.2.4.5 TypedArray ( buffer, byteOffset, length ) // ES #sec-typedarray-buffer-byteoffset-length - macro ConstructByArrayBuffer(implicit context: Context)( + transitioning macro ConstructByArrayBuffer(implicit context: Context)( typedArray: JSTypedArray, buffer: JSArrayBuffer, byteOffset: Object, length: Object, elementsInfo: typed_array::TypedArrayElementsInfo): void { try { diff --git a/deps/v8/src/builtins/typed-array-every.tq b/deps/v8/src/builtins/typed-array-every.tq new file mode 100644 index 0000000000..85b4a77618 --- /dev/null +++ b/deps/v8/src/builtins/typed-array-every.tq @@ -0,0 +1,53 @@ +// 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_every { + const kBuiltinName: constexpr string = '%TypedArray%.prototype.every'; + + transitioning macro EveryAllElements(implicit context: Context)( + array: typed_array::AttachedJSTypedArray, callbackfn: Callable, + thisArg: Object): Boolean { + let witness = typed_array::NewAttachedJSTypedArrayWitness(array); + const length: Smi = Convert<Smi>(witness.Get().length); + for (let k: Smi = 0; k < length; k++) { + // BUG(4895): We should throw on detached buffers rather than simply exit. + witness.Recheck() otherwise break; + const value: Object = witness.Load(k); + const result = + Call(context, callbackfn, thisArg, value, k, witness.GetStable()); + if (!ToBoolean(result)) { + return False; + } + } + return True; + } + + // https://tc39.github.io/ecma262/#sec-%typedarray%.prototype.every + transitioning javascript builtin + TypedArrayPrototypeEvery(implicit context: Context)( + receiver: Object, ...arguments): Object { + // arguments[0] = callback + // arguments[1] = thisArg + try { + const array: JSTypedArray = Cast<JSTypedArray>(receiver) + otherwise NotTypedArray; + const uarray = typed_array::EnsureAttached(array) otherwise IsDetached; + + const callbackfn = Cast<Callable>(arguments[0]) otherwise NotCallable; + const thisArg = arguments[1]; + return EveryAllElements(uarray, callbackfn, thisArg); + } + label NotCallable deferred { + ThrowTypeError(kCalledNonCallable, arguments[0]); + } + label NotTypedArray deferred { + ThrowTypeError(kNotTypedArray, kBuiltinName); + } + label IsDetached deferred { + ThrowTypeError(kDetachedOperation, kBuiltinName); + } + } +} diff --git a/deps/v8/src/builtins/typed-array-find.tq b/deps/v8/src/builtins/typed-array-find.tq new file mode 100644 index 0000000000..19b0602241 --- /dev/null +++ b/deps/v8/src/builtins/typed-array-find.tq @@ -0,0 +1,53 @@ +// 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_find { + const kBuiltinName: constexpr string = '%TypedArray%.prototype.find'; + + transitioning macro FindAllElements(implicit context: Context)( + array: typed_array::AttachedJSTypedArray, callbackfn: Callable, + thisArg: Object): Object { + let witness = typed_array::NewAttachedJSTypedArrayWitness(array); + const length: Smi = Convert<Smi>(witness.Get().length); + for (let k: Smi = 0; k < length; k++) { + // BUG(4895): We should throw on detached buffers rather than simply exit. + witness.Recheck() otherwise break; + const value: Object = witness.Load(k); + const result = + Call(context, callbackfn, thisArg, value, k, witness.GetStable()); + if (ToBoolean(result)) { + return value; + } + } + return Undefined; + } + + // https://tc39.github.io/ecma262/#sec-%typedarray%.prototype.find + transitioning javascript builtin + TypedArrayPrototypeFind(implicit context: + Context)(receiver: Object, ...arguments): Object { + // arguments[0] = callback + // arguments[1] = thisArg + try { + const array: JSTypedArray = Cast<JSTypedArray>(receiver) + otherwise NotTypedArray; + const uarray = typed_array::EnsureAttached(array) otherwise IsDetached; + + const callbackfn = Cast<Callable>(arguments[0]) otherwise NotCallable; + const thisArg = arguments[1]; + return FindAllElements(uarray, callbackfn, thisArg); + } + label NotCallable deferred { + ThrowTypeError(kCalledNonCallable, arguments[0]); + } + label NotTypedArray deferred { + ThrowTypeError(kNotTypedArray, kBuiltinName); + } + label IsDetached deferred { + ThrowTypeError(kDetachedOperation, kBuiltinName); + } + } +} diff --git a/deps/v8/src/builtins/typed-array-findindex.tq b/deps/v8/src/builtins/typed-array-findindex.tq new file mode 100644 index 0000000000..fd77774e21 --- /dev/null +++ b/deps/v8/src/builtins/typed-array-findindex.tq @@ -0,0 +1,53 @@ +// 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_findindex { + const kBuiltinName: constexpr string = '%TypedArray%.prototype.findIndex'; + + transitioning macro FindIndexAllElements(implicit context: Context)( + array: typed_array::AttachedJSTypedArray, callbackfn: Callable, + thisArg: Object): Number { + let witness = typed_array::NewAttachedJSTypedArrayWitness(array); + const length: Smi = Convert<Smi>(witness.Get().length); + for (let k: Smi = 0; k < length; k++) { + // BUG(4895): We should throw on detached buffers rather than simply exit. + witness.Recheck() otherwise break; + const value: Object = witness.Load(k); + const result = + Call(context, callbackfn, thisArg, value, k, witness.GetStable()); + if (ToBoolean(result)) { + return k; + } + } + return -1; + } + + // https://tc39.github.io/ecma262/#sec-%typedarray%.prototype.findIndex + transitioning javascript builtin + TypedArrayPrototypeFindIndex(implicit context: Context)( + receiver: Object, ...arguments): Object { + // arguments[0] = callback + // arguments[1] = thisArg. + try { + const array: JSTypedArray = Cast<JSTypedArray>(receiver) + otherwise NotTypedArray; + const uarray = typed_array::EnsureAttached(array) otherwise IsDetached; + + const callbackfn = Cast<Callable>(arguments[0]) otherwise NotCallable; + const thisArg = arguments[1]; + return FindIndexAllElements(uarray, callbackfn, thisArg); + } + label NotCallable deferred { + ThrowTypeError(kCalledNonCallable, arguments[0]); + } + label NotTypedArray deferred { + ThrowTypeError(kNotTypedArray, kBuiltinName); + } + label IsDetached deferred { + ThrowTypeError(kDetachedOperation, kBuiltinName); + } + } +} diff --git a/deps/v8/src/builtins/typed-array-some.tq b/deps/v8/src/builtins/typed-array-some.tq new file mode 100644 index 0000000000..f56d63c071 --- /dev/null +++ b/deps/v8/src/builtins/typed-array-some.tq @@ -0,0 +1,53 @@ +// 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_some { + const kBuiltinName: constexpr string = '%TypedArray%.prototype.some'; + + transitioning macro SomeAllElements(implicit context: Context)( + array: typed_array::AttachedJSTypedArray, callbackfn: Callable, + thisArg: Object): Boolean { + let witness = typed_array::NewAttachedJSTypedArrayWitness(array); + const length: Smi = Convert<Smi>(witness.Get().length); + for (let k: Smi = 0; k < length; k++) { + // BUG(4895): We should throw on detached buffers rather than simply exit. + witness.Recheck() otherwise break; + const value: Object = witness.Load(k); + const result = + Call(context, callbackfn, thisArg, value, k, witness.GetStable()); + if (ToBoolean(result)) { + return True; + } + } + return False; + } + + // https://tc39.github.io/ecma262/#sec-%typedarray%.prototype.some + transitioning javascript builtin + TypedArrayPrototypeSome(implicit context: + Context)(receiver: Object, ...arguments): Object { + // arguments[0] = callback + // arguments[1] = thisArg. + try { + const array: JSTypedArray = Cast<JSTypedArray>(receiver) + otherwise NotTypedArray; + const uarray = typed_array::EnsureAttached(array) otherwise IsDetached; + + const callbackfn = Cast<Callable>(arguments[0]) otherwise NotCallable; + const thisArg = arguments[1]; + return SomeAllElements(uarray, callbackfn, thisArg); + } + label NotCallable deferred { + ThrowTypeError(kCalledNonCallable, arguments[0]); + } + label NotTypedArray deferred { + ThrowTypeError(kNotTypedArray, kBuiltinName); + } + label IsDetached deferred { + ThrowTypeError(kDetachedOperation, kBuiltinName); + } + } +} diff --git a/deps/v8/src/builtins/typed-array.tq b/deps/v8/src/builtins/typed-array.tq index 607c9d225f..d86b48da05 100644 --- a/deps/v8/src/builtins/typed-array.tq +++ b/deps/v8/src/builtins/typed-array.tq @@ -111,9 +111,9 @@ namespace typed_array { AttachedJSTypedArrayWitness { const kind = array.elements_kind; return AttachedJSTypedArrayWitness{ - array, - array, - GetLoadFnForElementsKind(kind) + stable: array, + unstable: array, + loadfn: GetLoadFnForElementsKind(kind) }; } diff --git a/deps/v8/src/builtins/x64/builtins-x64.cc b/deps/v8/src/builtins/x64/builtins-x64.cc index 11bb9ca44a..bcdf5928e1 100644 --- a/deps/v8/src/builtins/x64/builtins-x64.cc +++ b/deps/v8/src/builtins/x64/builtins-x64.cc @@ -47,15 +47,11 @@ void Builtins::Generate_Adaptor(MacroAssembler* masm, Address address, static void GenerateTailCallToReturnedCode(MacroAssembler* masm, Runtime::FunctionId function_id) { // ----------- S t a t e ------------- - // -- rax : argument count (preserved for callee) // -- rdx : new target (preserved for callee) // -- rdi : target function (preserved for callee) // ----------------------------------- { FrameScope scope(masm, StackFrame::INTERNAL); - // Push the number of arguments to the callee. - __ SmiTag(rax, rax); - __ Push(rax); // Push a copy of the target function and the new target. __ Push(rdi); __ Push(rdx); @@ -68,8 +64,6 @@ static void GenerateTailCallToReturnedCode(MacroAssembler* masm, // Restore target function and new target. __ Pop(rdx); __ Pop(rdi); - __ Pop(rax); - __ SmiUntag(rax, rax); } static_assert(kJavaScriptCallCodeStartRegister == rcx, "ABI mismatch"); __ JumpCodeObject(rcx); @@ -77,6 +71,25 @@ static void GenerateTailCallToReturnedCode(MacroAssembler* masm, namespace { +void Generate_StackOverflowCheck( + MacroAssembler* masm, Register num_args, Register scratch, + Label* stack_overflow, + Label::Distance stack_overflow_distance = Label::kFar) { + // Check the stack for overflow. We are not trying to catch + // interruptions (e.g. debug break and preemption) here, so the "real stack + // limit" is checked. + __ LoadRoot(kScratchRegister, RootIndex::kRealStackLimit); + __ movq(scratch, rsp); + // Make scratch the space we have left. The stack might already be overflowed + // here which will cause scratch to become negative. + __ subq(scratch, kScratchRegister); + __ sarq(scratch, Immediate(kSystemPointerSizeLog2)); + // Check if the arguments will overflow the stack. + __ cmpq(scratch, num_args); + // Signed comparison. + __ j(less_equal, stack_overflow, stack_overflow_distance); +} + void Generate_JSBuiltinsConstructStubHelper(MacroAssembler* masm) { // ----------- S t a t e ------------- // -- rax: number of arguments @@ -85,6 +98,9 @@ void Generate_JSBuiltinsConstructStubHelper(MacroAssembler* masm) { // -- rsi: context // ----------------------------------- + Label stack_overflow; + Generate_StackOverflowCheck(masm, rax, rcx, &stack_overflow, Label::kFar); + // Enter a construct frame. { FrameScope scope(masm, StackFrame::CONSTRUCT); @@ -142,25 +158,13 @@ void Generate_JSBuiltinsConstructStubHelper(MacroAssembler* masm) { __ PushReturnAddressFrom(rcx); __ ret(0); -} -void Generate_StackOverflowCheck( - MacroAssembler* masm, Register num_args, Register scratch, - Label* stack_overflow, - Label::Distance stack_overflow_distance = Label::kFar) { - // Check the stack for overflow. We are not trying to catch - // interruptions (e.g. debug break and preemption) here, so the "real stack - // limit" is checked. - __ LoadRoot(kScratchRegister, RootIndex::kRealStackLimit); - __ movq(scratch, rsp); - // Make scratch the space we have left. The stack might already be overflowed - // here which will cause scratch to become negative. - __ subq(scratch, kScratchRegister); - __ sarq(scratch, Immediate(kSystemPointerSizeLog2)); - // Check if the arguments will overflow the stack. - __ cmpq(scratch, num_args); - // Signed comparison. - __ j(less_equal, stack_overflow, stack_overflow_distance); + __ bind(&stack_overflow); + { + FrameScope scope(masm, StackFrame::INTERNAL); + __ CallRuntime(Runtime::kThrowStackOverflow); + __ int3(); // This should be unreachable. + } } } // namespace @@ -891,13 +895,11 @@ static void MaybeTailCallOptimizedCodeSlot(MacroAssembler* masm, Register scratch1, Register scratch2, Register scratch3) { // ----------- S t a t e ------------- - // -- rax : argument count (preserved for callee if needed, and caller) // -- rdx : new target (preserved for callee if needed, and caller) // -- rdi : target function (preserved for callee if needed, and caller) // -- feedback vector (preserved for caller if needed) // ----------------------------------- - DCHECK(!AreAliased(feedback_vector, rax, rdx, rdi, scratch1, scratch2, - scratch3)); + DCHECK(!AreAliased(feedback_vector, rdx, rdi, scratch1, scratch2, scratch3)); Label optimized_code_slot_is_weak_ref, fallthrough; @@ -1086,7 +1088,10 @@ void Builtins::Generate_InterpreterEntryTrampoline(MacroAssembler* masm) { Label push_stack_frame; // Check if feedback vector is valid. If valid, check for optimized code // and update invocation count. Otherwise, setup the stack frame. - __ JumpIfRoot(feedback_vector, RootIndex::kUndefinedValue, &push_stack_frame); + __ LoadTaggedPointerField( + rcx, FieldOperand(feedback_vector, HeapObject::kMapOffset)); + __ CmpInstanceType(rcx, FEEDBACK_VECTOR_TYPE); + __ j(not_equal, &push_stack_frame); // Read off the optimized code slot in the feedback vector, and if there // is optimized code or an optimization marker, call that instead. @@ -1106,10 +1111,15 @@ void Builtins::Generate_InterpreterEntryTrampoline(MacroAssembler* masm) { __ Push(rsi); // Callee's context. __ Push(rdi); // Callee's JS function. - // Reset code age. - __ movb(FieldOperand(kInterpreterBytecodeArrayRegister, - BytecodeArray::kBytecodeAgeOffset), - Immediate(BytecodeArray::kNoAgeBytecodeAge)); + // Reset code age and the OSR arming. The OSR field and BytecodeAgeOffset are + // 8-bit fields next to each other, so we could just optimize by writing a + // 16-bit. These static asserts guard our assumption is valid. + STATIC_ASSERT(BytecodeArray::kBytecodeAgeOffset == + BytecodeArray::kOSRNestingLevelOffset + kCharSize); + STATIC_ASSERT(BytecodeArray::kNoAgeBytecodeAge == 0); + __ movw(FieldOperand(kInterpreterBytecodeArrayRegister, + BytecodeArray::kOSRNestingLevelOffset), + Immediate(0)); // Load initial bytecode offset. __ movq(kInterpreterBytecodeOffsetRegister, |