diff options
Diffstat (limited to 'deps/v8/src/builtins')
132 files changed, 4673 insertions, 3826 deletions
diff --git a/deps/v8/src/builtins/OWNERS b/deps/v8/src/builtins/OWNERS index 450423f878..f52e1c9ca8 100644 --- a/deps/v8/src/builtins/OWNERS +++ b/deps/v8/src/builtins/OWNERS @@ -1,3 +1,3 @@ -file://COMMON_OWNERS +file:../../COMMON_OWNERS # COMPONENT: Blink>JavaScript>Runtime diff --git a/deps/v8/src/builtins/arguments.tq b/deps/v8/src/builtins/arguments.tq index 6df5f801a3..18d6c23b3d 100644 --- a/deps/v8/src/builtins/arguments.tq +++ b/deps/v8/src/builtins/arguments.tq @@ -8,7 +8,7 @@ struct Arguments { const length: intptr; } -extern operator '[]' macro GetArgumentValue(Arguments, intptr): Object; +extern operator '[]' macro GetArgumentValue(Arguments, intptr): JSAny; extern macro GetFrameArguments(FrameWithArguments, intptr): Arguments; diff --git a/deps/v8/src/builtins/arm/builtins-arm.cc b/deps/v8/src/builtins/arm/builtins-arm.cc index 9b9956b0fb..e9b562620f 100644 --- a/deps/v8/src/builtins/arm/builtins-arm.cc +++ b/deps/v8/src/builtins/arm/builtins-arm.cc @@ -90,12 +90,24 @@ static void GenerateTailCallToReturnedCode(MacroAssembler* masm, namespace { +void LoadRealStackLimit(MacroAssembler* masm, Register destination) { + DCHECK(masm->root_array_available()); + Isolate* isolate = masm->isolate(); + ExternalReference limit = ExternalReference::address_of_real_jslimit(isolate); + DCHECK(TurboAssembler::IsAddressableThroughRootRegister(isolate, limit)); + + intptr_t offset = + TurboAssembler::RootRegisterOffsetForExternalReference(isolate, limit); + CHECK(is_int32(offset)); + __ ldr(destination, MemOperand(kRootRegister, offset)); +} + 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); + LoadRealStackLimit(masm, scratch); // 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); @@ -428,7 +440,8 @@ void Builtins::Generate_ResumeGeneratorTrampoline(MacroAssembler* masm) { // Check the stack for overflow. We are not trying to catch interruptions // (i.e. debug break and preemption) here, so check the "real stack limit". Label stack_overflow; - __ CompareRoot(sp, RootIndex::kRealStackLimit); + LoadRealStackLimit(masm, scratch); + __ cmp(sp, scratch); __ b(lo, &stack_overflow); // Push receiver. @@ -1116,7 +1129,7 @@ void Builtins::Generate_InterpreterEntryTrampoline(MacroAssembler* masm) { // Do a stack check to ensure we don't go over the limit. Label ok; __ sub(r9, sp, Operand(r4)); - __ LoadRoot(r2, RootIndex::kRealStackLimit); + LoadRealStackLimit(masm, r2); __ cmp(r9, Operand(r2)); __ b(hs, &ok); __ CallRuntime(Runtime::kThrowStackOverflow); @@ -2089,7 +2102,7 @@ void Generate_PushBoundArguments(MacroAssembler* masm) { // Compute the space we have left. The stack might already be overflowed // here which will cause remaining_stack_size to become negative. - __ LoadRoot(remaining_stack_size, RootIndex::kRealStackLimit); + LoadRealStackLimit(masm, remaining_stack_size); __ sub(remaining_stack_size, sp, remaining_stack_size); // Check if the arguments will overflow the stack. @@ -2517,7 +2530,10 @@ void Builtins::Generate_WasmCompileLazy(MacroAssembler* masm) { __ push(kWasmCompileLazyFuncIndexRegister); // Load the correct CEntry builtin from the instance object. __ ldr(r2, FieldMemOperand(kWasmInstanceRegister, - WasmInstanceObject::kCEntryStubOffset)); + WasmInstanceObject::kIsolateRootOffset)); + auto centry_id = + Builtins::kCEntry_Return1_DontSaveFPRegs_ArgvOnStack_NoBuiltinExit; + __ ldr(r2, MemOperand(r2, IsolateData::builtin_slot_offset(centry_id))); // Initialize the JavaScript context with 0. CEntry will use it to // set the current context on the isolate. __ Move(cp, Smi::zero()); diff --git a/deps/v8/src/builtins/arm64/builtins-arm64.cc b/deps/v8/src/builtins/arm64/builtins-arm64.cc index bcee8f0b5d..4e159a69b7 100644 --- a/deps/v8/src/builtins/arm64/builtins-arm64.cc +++ b/deps/v8/src/builtins/arm64/builtins-arm64.cc @@ -24,6 +24,10 @@ #include "src/runtime/runtime.h" #include "src/wasm/wasm-objects.h" +#if defined(V8_OS_WIN) +#include "src/diagnostics/unwinding-info-win64.h" +#endif // V8_OS_WIN + namespace v8 { namespace internal { @@ -85,6 +89,17 @@ static void GenerateTailCallToReturnedCode(MacroAssembler* masm, namespace { +void LoadRealStackLimit(MacroAssembler* masm, Register destination) { + DCHECK(masm->root_array_available()); + Isolate* isolate = masm->isolate(); + ExternalReference limit = ExternalReference::address_of_real_jslimit(isolate); + DCHECK(TurboAssembler::IsAddressableThroughRootRegister(isolate, limit)); + + intptr_t offset = + TurboAssembler::RootRegisterOffsetForExternalReference(isolate, limit); + __ Ldr(destination, MemOperand(kRootRegister, offset)); +} + void Generate_StackOverflowCheck(MacroAssembler* masm, Register num_args, Label* stack_overflow) { UseScratchRegisterScope temps(masm); @@ -94,7 +109,7 @@ void Generate_StackOverflowCheck(MacroAssembler* masm, Register num_args, // 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); + LoadRealStackLimit(masm, scratch); // 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); @@ -476,7 +491,8 @@ void Builtins::Generate_ResumeGeneratorTrampoline(MacroAssembler* masm) { // Check the stack for overflow. We are not trying to catch interruptions // (i.e. debug break and preemption) here, so check the "real stack limit". Label stack_overflow; - __ CompareRoot(sp, RootIndex::kRealStackLimit); + LoadRealStackLimit(masm, x10); + __ Cmp(sp, x10); __ B(lo, &stack_overflow); // Get number of arguments for generator function. @@ -623,6 +639,23 @@ void Generate_JSEntryVariant(MacroAssembler* masm, StackFrame::Type type, // will have no effect on the model or real hardware. __ EnableInstrumentation(); +#if defined(V8_OS_WIN) + // Windows ARM64 relies on a frame pointer (fp/x29 which are aliases to each + // other) chain to do stack unwinding, but JSEntry breaks that by setting fp + // to point to bad_frame_pointer below. To fix unwind information for this + // case, JSEntry registers the offset (from current fp to the caller's fp + // saved by PushCalleeSavedRegisters on stack) to xdata_encoder which then + // emits the offset value as part of result unwind data accordingly. The + // current offset is kFramePointerOffset which includes bad_frame_pointer + // saved below plus kFramePointerOffsetInPushCalleeSavedRegisters. + const int kFramePointerOffset = + kFramePointerOffsetInPushCalleeSavedRegisters + kSystemPointerSize; + win64_unwindinfo::XdataEncoder* xdata_encoder = masm->GetXdataEncoder(); + if (xdata_encoder) { + xdata_encoder->onFramePointerAdjustment(kFramePointerOffset); + } +#endif + __ PushCalleeSavedRegisters(); // Set up the reserved register for 0.0. @@ -1223,7 +1256,12 @@ void Builtins::Generate_InterpreterEntryTrampoline(MacroAssembler* masm) { // Do a stack check to ensure we don't go over the limit. Label ok; __ Sub(x10, sp, Operand(x11)); - __ CompareRoot(x10, RootIndex::kRealStackLimit); + { + UseScratchRegisterScope temps(masm); + Register scratch = temps.AcquireX(); + LoadRealStackLimit(masm, scratch); + __ Cmp(x10, scratch); + } __ B(hs, &ok); __ CallRuntime(Runtime::kThrowStackOverflow); __ Bind(&ok); @@ -2469,7 +2507,7 @@ void Generate_PushBoundArguments(MacroAssembler* masm) { // (i.e. debug break and preemption) here, so check the "real stack // limit". Label done; - __ LoadRoot(x10, RootIndex::kRealStackLimit); + LoadRealStackLimit(masm, x10); // Make x10 the space we have left. The stack might already be overflowed // here which will cause x10 to become negative. __ Sub(x10, sp, x10); @@ -3031,9 +3069,12 @@ void Builtins::Generate_WasmCompileLazy(MacroAssembler* masm) { // function. __ Push(kWasmInstanceRegister, kWasmCompileLazyFuncIndexRegister); // Load the correct CEntry builtin from the instance object. + __ Ldr(x2, FieldMemOperand(kWasmInstanceRegister, + WasmInstanceObject::kIsolateRootOffset)); + auto centry_id = + Builtins::kCEntry_Return1_DontSaveFPRegs_ArgvOnStack_NoBuiltinExit; __ LoadTaggedPointerField( - x2, FieldMemOperand(kWasmInstanceRegister, - WasmInstanceObject::kCEntryStubOffset)); + x2, MemOperand(x2, IsolateData::builtin_slot_offset(centry_id))); // Initialize the JavaScript context with 0. CEntry will use it to // set the current context on the isolate. __ Mov(cp, Smi::zero()); diff --git a/deps/v8/src/builtins/array-copywithin.tq b/deps/v8/src/builtins/array-copywithin.tq index 94d871e8f7..574eaf9b9d 100644 --- a/deps/v8/src/builtins/array-copywithin.tq +++ b/deps/v8/src/builtins/array-copywithin.tq @@ -9,7 +9,7 @@ namespace array_copywithin { // https://tc39.github.io/ecma262/#sec-array.prototype.copyWithin transitioning javascript builtin ArrayPrototypeCopyWithin( - js-implicit context: Context, receiver: Object)(...arguments): Object { + js-implicit context: Context, receiver: JSAny)(...arguments): JSAny { // 1. Let O be ? ToObject(this value). const object: JSReceiver = ToObject_Inline(context, receiver); @@ -68,7 +68,7 @@ namespace array_copywithin { // d. If fromPresent is true, then. if (fromPresent == True) { // i. Let fromVal be ? Get(O, fromKey). - const fromVal: Object = GetProperty(object, from); + const fromVal: JSAny = GetProperty(object, from); // ii. Perform ? Set(O, toKey, fromVal, true). SetProperty(object, to, fromVal); diff --git a/deps/v8/src/builtins/array-every.tq b/deps/v8/src/builtins/array-every.tq index 3451cd769b..8f4c0e1f23 100644 --- a/deps/v8/src/builtins/array-every.tq +++ b/deps/v8/src/builtins/array-every.tq @@ -5,15 +5,14 @@ namespace array { transitioning javascript builtin ArrayEveryLoopEagerDeoptContinuation( - js-implicit context: Context, receiver: Object)( - callback: Object, thisArg: Object, initialK: Object, - length: Object): Object { + js-implicit context: Context, receiver: JSAny)( + callback: JSAny, thisArg: JSAny, initialK: JSAny, length: JSAny): JSAny { // All continuation points in the optimized every implementation are // after the ToObject(O) call that ensures we are dealing with a // JSReceiver. // // Also, this great mass of casts is necessary because the signature - // of Torque javascript builtins requires Object type for all parameters + // of Torque javascript builtins requires JSAny type for all parameters // other than {context}. const jsreceiver = Cast<JSReceiver>(receiver) otherwise unreachable; const callbackfn = Cast<Callable>(callback) otherwise unreachable; @@ -27,9 +26,9 @@ namespace array { transitioning javascript builtin ArrayEveryLoopLazyDeoptContinuation( - js-implicit context: Context, receiver: Object)( - callback: Object, thisArg: Object, initialK: Object, length: Object, - result: Object): Object { + js-implicit context: Context, receiver: JSAny)( + callback: JSAny, thisArg: JSAny, initialK: JSAny, length: JSAny, + result: JSAny): JSAny { // All continuation points in the optimized every implementation are // after the ToObject(O) call that ensures we are dealing with a // JSReceiver. @@ -53,9 +52,9 @@ namespace array { } transitioning builtin ArrayEveryLoopContinuation(implicit context: Context)( - _receiver: JSReceiver, callbackfn: Callable, thisArg: Object, - _array: Object, o: JSReceiver, initialK: Number, length: Number, - _initialTo: Object): Object { + _receiver: JSReceiver, callbackfn: Callable, thisArg: JSAny, + _array: JSAny, o: JSReceiver, initialK: Number, length: Number, + _initialTo: JSAny): JSAny { // 5. Let k be 0. // 6. Repeat, while k < len for (let k: Number = initialK; k < length; k++) { @@ -69,10 +68,10 @@ namespace array { // 6c. If kPresent is true, then if (kPresent == True) { // 6c. i. Let kValue be ? Get(O, Pk). - const kValue: Object = GetProperty(o, k); + const kValue: JSAny = GetProperty(o, k); // 6c. ii. Perform ? Call(callbackfn, T, <kValue, k, O>). - const result: Object = Call(context, callbackfn, thisArg, kValue, k, o); + const result: JSAny = Call(context, callbackfn, thisArg, kValue, k, o); // iii. If selected is true, then... if (!ToBoolean(result)) { @@ -86,7 +85,7 @@ namespace array { } transitioning macro FastArrayEvery(implicit context: Context)( - o: JSReceiver, len: Number, callbackfn: Callable, thisArg: Object): Object + o: JSReceiver, len: Number, callbackfn: Callable, thisArg: JSAny): JSAny labels Bailout(Smi) { let k: Smi = 0; const smiLen = Cast<Smi>(len) otherwise goto Bailout(k); @@ -99,8 +98,8 @@ namespace array { // Ensure that we haven't walked beyond a possibly updated length. if (k >= fastOW.Get().length) goto Bailout(k); - const value: Object = fastOW.LoadElementNoHole(k) otherwise continue; - const result: Object = + const value: JSAny = fastOW.LoadElementNoHole(k) otherwise continue; + const result: JSAny = Call(context, callbackfn, thisArg, value, k, fastOW.Get()); if (!ToBoolean(result)) { return False; @@ -111,8 +110,8 @@ namespace array { // https://tc39.github.io/ecma262/#sec-array.prototype.every transitioning javascript builtin - ArrayEvery(js-implicit context: Context, receiver: Object)(...arguments): - Object { + ArrayEvery(js-implicit context: Context, receiver: JSAny)(...arguments): + JSAny { try { RequireObjectCoercible(receiver, 'Array.prototype.every'); @@ -129,7 +128,7 @@ namespace array { const callbackfn = Cast<Callable>(arguments[0]) otherwise TypeError; // 4. If thisArg is present, let T be thisArg; else let T be undefined. - const thisArg: Object = arguments.length > 1 ? arguments[1] : Undefined; + const thisArg: JSAny = arguments.length > 1 ? arguments[1] : Undefined; // Special cases. try { diff --git a/deps/v8/src/builtins/array-filter.tq b/deps/v8/src/builtins/array-filter.tq index 9acd0d04ee..4d23144329 100644 --- a/deps/v8/src/builtins/array-filter.tq +++ b/deps/v8/src/builtins/array-filter.tq @@ -5,15 +5,15 @@ namespace array_filter { transitioning javascript builtin ArrayFilterLoopEagerDeoptContinuation( - js-implicit context: Context, receiver: Object)( - callback: Object, thisArg: Object, array: Object, initialK: Object, - length: Object, initialTo: Object): Object { + js-implicit context: Context, receiver: JSAny)( + callback: JSAny, thisArg: JSAny, array: JSAny, initialK: JSAny, + length: JSAny, initialTo: JSAny): JSAny { // All continuation points in the optimized filter implementation are // after the ToObject(O) call that ensures we are dealing with a // JSReceiver. // // Also, this great mass of casts is necessary because the signature - // of Torque javascript builtins requires Object type for all parameters + // of Torque javascript builtins requires JSAny type for all parameters // other than {context}. const jsreceiver = Cast<JSReceiver>(receiver) otherwise unreachable; const callbackfn = Cast<Callable>(callback) otherwise unreachable; @@ -29,10 +29,9 @@ namespace array_filter { transitioning javascript builtin ArrayFilterLoopLazyDeoptContinuation( - js-implicit context: Context, receiver: Object)( - callback: Object, thisArg: Object, array: Object, initialK: Object, - length: Object, valueK: Object, initialTo: Object, - result: Object): Object { + js-implicit context: Context, receiver: JSAny)( + callback: JSAny, thisArg: JSAny, array: JSAny, initialK: JSAny, + length: JSAny, valueK: JSAny, initialTo: JSAny, result: JSAny): JSAny { // All continuation points in the optimized filter implementation are // after the ToObject(O) call that ensures we are dealing with a // JSReceiver. @@ -60,9 +59,9 @@ namespace array_filter { } transitioning builtin ArrayFilterLoopContinuation(implicit context: Context)( - _receiver: JSReceiver, callbackfn: Callable, thisArg: Object, + _receiver: JSReceiver, callbackfn: Callable, thisArg: JSAny, array: JSReceiver, o: JSReceiver, initialK: Number, length: Number, - initialTo: Number): Object { + initialTo: Number): JSAny { let to: Number = initialTo; // 5. Let k be 0. // 6. Repeat, while k < len @@ -77,10 +76,10 @@ namespace array_filter { // 6c. If kPresent is true, then if (kPresent == True) { // 6c. i. Let kValue be ? Get(O, Pk). - const kValue: Object = GetProperty(o, k); + const kValue: JSAny = GetProperty(o, k); // 6c. ii. Perform ? Call(callbackfn, T, <kValue, k, O>). - const result: Object = Call(context, callbackfn, thisArg, kValue, k, o); + const result: JSAny = Call(context, callbackfn, thisArg, kValue, k, o); // iii. If selected is true, then... if (ToBoolean(result)) { @@ -97,7 +96,7 @@ namespace array_filter { } transitioning macro FastArrayFilter(implicit context: Context)( - fastO: FastJSArray, len: Smi, callbackfn: Callable, thisArg: Object, + fastO: FastJSArray, len: Smi, callbackfn: Callable, thisArg: JSAny, output: FastJSArray) labels Bailout(Number, Number) { let k: Smi = 0; let to: Smi = 0; @@ -112,8 +111,8 @@ namespace array_filter { // Ensure that we haven't walked beyond a possibly updated length. if (k >= fastOW.Get().length) goto Bailout(k, to); - const value: Object = fastOW.LoadElementNoHole(k) otherwise continue; - const result: Object = + const value: JSAny = fastOW.LoadElementNoHole(k) otherwise continue; + const result: JSAny = Call(context, callbackfn, thisArg, value, k, fastOW.Get()); if (ToBoolean(result)) { try { @@ -147,8 +146,8 @@ namespace array_filter { // https://tc39.github.io/ecma262/#sec-array.prototype.filter transitioning javascript builtin - ArrayFilter(js-implicit context: Context, receiver: Object)(...arguments): - Object { + ArrayFilter(js-implicit context: Context, receiver: JSAny)(...arguments): + JSAny { try { RequireObjectCoercible(receiver, 'Array.prototype.filter'); @@ -165,7 +164,7 @@ namespace array_filter { const callbackfn = Cast<Callable>(arguments[0]) otherwise TypeError; // 4. If thisArg is present, let T be thisArg; else let T be undefined. - const thisArg: Object = arguments.length > 1 ? arguments[1] : Undefined; + const thisArg: JSAny = arguments.length > 1 ? arguments[1] : Undefined; let output: JSReceiver; // Special cases. diff --git a/deps/v8/src/builtins/array-find.tq b/deps/v8/src/builtins/array-find.tq index ef54dd4666..ec840a4c98 100644 --- a/deps/v8/src/builtins/array-find.tq +++ b/deps/v8/src/builtins/array-find.tq @@ -5,15 +5,14 @@ namespace array_find { transitioning javascript builtin ArrayFindLoopEagerDeoptContinuation( - js-implicit context: Context, receiver: Object)( - callback: Object, thisArg: Object, initialK: Object, - length: Object): Object { + js-implicit context: Context, receiver: JSAny)( + callback: JSAny, thisArg: JSAny, initialK: JSAny, length: JSAny): JSAny { // All continuation points in the optimized find implementation are // after the ToObject(O) call that ensures we are dealing with a // JSReceiver. // // Also, this great mass of casts is necessary because the signature - // of Torque javascript builtins requires Object type for all parameters + // of Torque javascript builtins requires JSAny type for all parameters // other than {context}. const jsreceiver = Cast<JSReceiver>(receiver) otherwise unreachable; const callbackfn = Cast<Callable>(callback) otherwise unreachable; @@ -26,9 +25,9 @@ namespace array_find { transitioning javascript builtin ArrayFindLoopLazyDeoptContinuation( - js-implicit context: Context, receiver: Object)( - _callback: Object, _thisArg: Object, _initialK: Object, _length: Object, - _result: Object): Object { + js-implicit context: Context, receiver: JSAny)( + _callback: JSAny, _thisArg: JSAny, _initialK: JSAny, _length: JSAny, + _result: JSAny): JSAny { // This deopt continuation point is never actually called, it just // exists to make stack traces correct from a ThrowTypeError if the // callback was found to be non-callable. @@ -40,9 +39,9 @@ namespace array_find { // before iteration continues. transitioning javascript builtin ArrayFindLoopAfterCallbackLazyDeoptContinuation( - js-implicit context: Context, receiver: Object)( - callback: Object, thisArg: Object, initialK: Object, length: Object, - foundValue: Object, isFound: Object): Object { + js-implicit context: Context, receiver: JSAny)( + callback: JSAny, thisArg: JSAny, initialK: JSAny, length: JSAny, + foundValue: JSAny, isFound: JSAny): JSAny { // All continuation points in the optimized find implementation are // after the ToObject(O) call that ensures we are dealing with a // JSReceiver. @@ -65,8 +64,8 @@ namespace array_find { } transitioning builtin ArrayFindLoopContinuation(implicit context: Context)( - _receiver: JSReceiver, callbackfn: Callable, thisArg: Object, - o: JSReceiver, initialK: Number, length: Number): Object { + _receiver: JSReceiver, callbackfn: Callable, thisArg: JSAny, + o: JSReceiver, initialK: Number, length: Number): JSAny { // 5. Let k be 0. // 6. Repeat, while k < len for (let k: Number = initialK; k < length; k++) { @@ -75,12 +74,11 @@ namespace array_find { // side-effect free and HasProperty/GetProperty do the conversion inline. // 6b. i. Let kValue be ? Get(O, Pk). - const value: Object = GetProperty(o, k); + const value: JSAny = GetProperty(o, k); // 6c. Let testResult be ToBoolean(? Call(predicate, T, <<kValue, k, // O>>)). - const testResult: Object = - Call(context, callbackfn, thisArg, value, k, o); + const testResult: JSAny = Call(context, callbackfn, thisArg, value, k, o); // 6d. If testResult is true, return kValue. if (ToBoolean(testResult)) { @@ -93,7 +91,7 @@ namespace array_find { } transitioning macro FastArrayFind(implicit context: Context)( - o: JSReceiver, len: Number, callbackfn: Callable, thisArg: Object): Object + o: JSReceiver, len: Number, callbackfn: Callable, thisArg: JSAny): JSAny labels Bailout(Smi) { let k: Smi = 0; const smiLen = Cast<Smi>(len) otherwise goto Bailout(k); @@ -107,8 +105,8 @@ namespace array_find { // Ensure that we haven't walked beyond a possibly updated length. if (k >= fastOW.Get().length) goto Bailout(k); - const value: Object = fastOW.LoadElementOrUndefined(k); - const testResult: Object = + const value: JSAny = fastOW.LoadElementOrUndefined(k); + const testResult: JSAny = Call(context, callbackfn, thisArg, value, k, fastOW.Get()); if (ToBoolean(testResult)) { return value; @@ -119,8 +117,8 @@ namespace array_find { // https://tc39.github.io/ecma262/#sec-array.prototype.find transitioning javascript builtin - ArrayPrototypeFind(js-implicit context: Context, receiver: Object)( - ...arguments): Object { + ArrayPrototypeFind(js-implicit context: Context, receiver: JSAny)( + ...arguments): JSAny { try { RequireObjectCoercible(receiver, 'Array.prototype.find'); @@ -138,7 +136,7 @@ namespace array_find { Cast<Callable>(arguments[0]) otherwise NotCallableError; // 4. If thisArg is present, let T be thisArg; else let T be undefined. - const thisArg: Object = arguments.length > 1 ? arguments[1] : Undefined; + const thisArg: JSAny = arguments.length > 1 ? arguments[1] : Undefined; // Special cases. try { diff --git a/deps/v8/src/builtins/array-findindex.tq b/deps/v8/src/builtins/array-findindex.tq index 5a8bb85fba..6145c81464 100644 --- a/deps/v8/src/builtins/array-findindex.tq +++ b/deps/v8/src/builtins/array-findindex.tq @@ -5,15 +5,14 @@ namespace array_findindex { transitioning javascript builtin ArrayFindIndexLoopEagerDeoptContinuation( - js-implicit context: Context, receiver: Object)( - callback: Object, thisArg: Object, initialK: Object, - length: Object): Object { + js-implicit context: Context, receiver: JSAny)( + callback: JSAny, thisArg: JSAny, initialK: JSAny, length: JSAny): JSAny { // All continuation points in the optimized findIndex implementation are // after the ToObject(O) call that ensures we are dealing with a // JSReceiver. // // Also, this great mass of casts is necessary because the signature - // of Torque javascript builtins requires Object type for all parameters + // of Torque javascript builtins requires JSAny type for all parameters // other than {context}. const jsreceiver = Cast<JSReceiver>(receiver) otherwise unreachable; const callbackfn = Cast<Callable>(callback) otherwise unreachable; @@ -26,9 +25,9 @@ namespace array_findindex { transitioning javascript builtin ArrayFindIndexLoopLazyDeoptContinuation( - js-implicit context: Context, receiver: Object)( - _callback: Object, _thisArg: Object, _initialK: Object, _length: Object, - _result: Object): Object { + js-implicit context: Context, receiver: JSAny)( + _callback: JSAny, _thisArg: JSAny, _initialK: JSAny, _length: JSAny, + _result: JSAny): JSAny { // This deopt continuation point is never actually called, it just // exists to make stack traces correct from a ThrowTypeError if the // callback was found to be non-callable. @@ -40,9 +39,9 @@ namespace array_findindex { // before iteration continues. transitioning javascript builtin ArrayFindIndexLoopAfterCallbackLazyDeoptContinuation( - js-implicit context: Context, receiver: Object)( - callback: Object, thisArg: Object, initialK: Object, length: Object, - foundValue: Object, isFound: Object): Object { + js-implicit context: Context, receiver: JSAny)( + callback: JSAny, thisArg: JSAny, initialK: JSAny, length: JSAny, + foundValue: JSAny, isFound: JSAny): JSAny { // All continuation points in the optimized findIndex implementation are // after the ToObject(O) call that ensures we are dealing with a // JSReceiver. @@ -66,7 +65,7 @@ namespace array_findindex { transitioning builtin ArrayFindIndexLoopContinuation(implicit context: Context)( - _receiver: JSReceiver, callbackfn: Callable, thisArg: Object, + _receiver: JSReceiver, callbackfn: Callable, thisArg: JSAny, o: JSReceiver, initialK: Number, length: Number): Number { // 5. Let k be 0. // 6. Repeat, while k < len @@ -76,12 +75,11 @@ namespace array_findindex { // side-effect free and HasProperty/GetProperty do the conversion inline. // 6b. i. Let kValue be ? Get(O, Pk). - const value: Object = GetProperty(o, k); + const value: JSAny = GetProperty(o, k); // 6c. Let testResult be ToBoolean(? Call(predicate, T, <<kValue, k, // O>>)). - const testResult: Object = - Call(context, callbackfn, thisArg, value, k, o); + const testResult: JSAny = Call(context, callbackfn, thisArg, value, k, o); // 6d. If testResult is true, return k. if (ToBoolean(testResult)) { @@ -94,7 +92,7 @@ namespace array_findindex { } transitioning macro FastArrayFindIndex(implicit context: Context)( - o: JSReceiver, len: Number, callbackfn: Callable, thisArg: Object): Number + o: JSReceiver, len: Number, callbackfn: Callable, thisArg: JSAny): Number labels Bailout(Smi) { let k: Smi = 0; const smiLen = Cast<Smi>(len) otherwise goto Bailout(k); @@ -108,8 +106,8 @@ namespace array_findindex { // Ensure that we haven't walked beyond a possibly updated length. if (k >= fastOW.Get().length) goto Bailout(k); - const value: Object = fastOW.LoadElementOrUndefined(k); - const testResult: Object = + const value: JSAny = fastOW.LoadElementOrUndefined(k); + const testResult: JSAny = Call(context, callbackfn, thisArg, value, k, fastOW.Get()); if (ToBoolean(testResult)) { return k; @@ -120,8 +118,8 @@ namespace array_findindex { // https://tc39.github.io/ecma262/#sec-array.prototype.findIndex transitioning javascript builtin - ArrayPrototypeFindIndex(js-implicit context: Context, receiver: Object)( - ...arguments): Object { + ArrayPrototypeFindIndex(js-implicit context: Context, receiver: JSAny)( + ...arguments): JSAny { try { RequireObjectCoercible(receiver, 'Array.prototype.findIndex'); @@ -139,7 +137,7 @@ namespace array_findindex { Cast<Callable>(arguments[0]) otherwise NotCallableError; // 4. If thisArg is present, let T be thisArg; else let T be undefined. - const thisArg: Object = arguments.length > 1 ? arguments[1] : Undefined; + const thisArg: JSAny = arguments.length > 1 ? arguments[1] : Undefined; // Special cases. try { diff --git a/deps/v8/src/builtins/array-foreach.tq b/deps/v8/src/builtins/array-foreach.tq index f52d944291..5b6e392601 100644 --- a/deps/v8/src/builtins/array-foreach.tq +++ b/deps/v8/src/builtins/array-foreach.tq @@ -5,9 +5,8 @@ namespace array_foreach { transitioning javascript builtin ArrayForEachLoopEagerDeoptContinuation( - js-implicit context: Context, receiver: Object)( - callback: Object, thisArg: Object, initialK: Object, - length: Object): Object { + js-implicit context: Context, receiver: JSAny)( + callback: JSAny, thisArg: JSAny, initialK: JSAny, length: JSAny): JSAny { // All continuation points in the optimized forEach implemntation are // after the ToObject(O) call that ensures we are dealing with a // JSReceiver. @@ -23,9 +22,9 @@ namespace array_foreach { transitioning javascript builtin ArrayForEachLoopLazyDeoptContinuation( - js-implicit context: Context, receiver: Object)( - callback: Object, thisArg: Object, initialK: Object, length: Object, - _result: Object): Object { + js-implicit context: Context, receiver: JSAny)( + callback: JSAny, thisArg: JSAny, initialK: JSAny, length: JSAny, + _result: JSAny): JSAny { // All continuation points in the optimized forEach implemntation are // after the ToObject(O) call that ensures we are dealing with a // JSReceiver. @@ -40,9 +39,9 @@ namespace array_foreach { } transitioning builtin ArrayForEachLoopContinuation(implicit context: Context)( - _receiver: JSReceiver, callbackfn: Callable, thisArg: Object, - _array: Object, o: JSReceiver, initialK: Number, len: Number, - _to: Object): Object { + _receiver: JSReceiver, callbackfn: Callable, thisArg: JSAny, + _array: JSAny, o: JSReceiver, initialK: Number, len: Number, + _to: JSAny): JSAny { // variables {array} and {to} are ignored. // 5. Let k be 0. @@ -58,7 +57,7 @@ namespace array_foreach { // 6c. If kPresent is true, then if (kPresent == True) { // 6c. i. Let kValue be ? Get(O, Pk). - const kValue: Object = GetProperty(o, k); + const kValue: JSAny = GetProperty(o, k); // 6c. ii. Perform ? Call(callbackfn, T, <kValue, k, O>). Call(context, callbackfn, thisArg, kValue, k, o); @@ -70,7 +69,7 @@ namespace array_foreach { } transitioning macro FastArrayForEach(implicit context: Context)( - o: JSReceiver, len: Number, callbackfn: Callable, thisArg: Object): Object + o: JSReceiver, len: Number, callbackfn: Callable, thisArg: JSAny): JSAny labels Bailout(Smi) { let k: Smi = 0; const smiLen = Cast<Smi>(len) otherwise goto Bailout(k); @@ -83,7 +82,7 @@ namespace array_foreach { // Ensure that we haven't walked beyond a possibly updated length. if (k >= fastOW.Get().length) goto Bailout(k); - const value: Object = fastOW.LoadElementNoHole(k) + const value: JSAny = fastOW.LoadElementNoHole(k) otherwise continue; Call(context, callbackfn, thisArg, value, k, fastOW.Get()); } @@ -92,8 +91,8 @@ namespace array_foreach { // https://tc39.github.io/ecma262/#sec-array.prototype.foreach transitioning javascript builtin - ArrayForEach(js-implicit context: Context, receiver: Object)(...arguments): - Object { + ArrayForEach(js-implicit context: Context, receiver: JSAny)(...arguments): + JSAny { try { RequireObjectCoercible(receiver, 'Array.prototype.forEach'); @@ -110,7 +109,7 @@ namespace array_foreach { const callbackfn = Cast<Callable>(arguments[0]) otherwise TypeError; // 4. If thisArg is present, let T be thisArg; else let T be undefined. - const thisArg: Object = arguments.length > 1 ? arguments[1] : Undefined; + const thisArg: JSAny = arguments.length > 1 ? arguments[1] : Undefined; // Special cases. let k: Number = 0; diff --git a/deps/v8/src/builtins/array-join.tq b/deps/v8/src/builtins/array-join.tq index c04233b222..08b5221e09 100644 --- a/deps/v8/src/builtins/array-join.tq +++ b/deps/v8/src/builtins/array-join.tq @@ -3,7 +3,7 @@ // found in the LICENSE file. namespace array_join { - type LoadJoinElementFn = builtin(Context, JSReceiver, Number) => Object; + type LoadJoinElementFn = builtin(Context, JSReceiver, Number) => JSAny; // Fast C call to write a fixed array (see Buffer.fixedArray) to a single // string. @@ -12,12 +12,12 @@ namespace array_join { FixedArray, intptr, String, String): String; transitioning builtin LoadJoinElement<T: type>( - context: Context, receiver: JSReceiver, k: Number): Object { + context: Context, receiver: JSReceiver, k: Number): JSAny { return GetProperty(receiver, k); } - LoadJoinElement<array::DictionaryElements>( - context: Context, receiver: JSReceiver, k: Number): Object { + transitioning LoadJoinElement<array::DictionaryElements>( + context: Context, receiver: JSReceiver, k: Number): JSAny { const array: JSArray = UnsafeCast<JSArray>(receiver); const dict: NumberDictionary = UnsafeCast<NumberDictionary>(array.elements); try { @@ -33,15 +33,15 @@ namespace array_join { } LoadJoinElement<array::FastSmiOrObjectElements>( - context: Context, receiver: JSReceiver, k: Number): Object { + context: Context, receiver: JSReceiver, k: Number): JSAny { const array: JSArray = UnsafeCast<JSArray>(receiver); const fixedArray: FixedArray = UnsafeCast<FixedArray>(array.elements); const element: Object = fixedArray.objects[UnsafeCast<Smi>(k)]; - return element == TheHole ? kEmptyString : element; + return element == TheHole ? kEmptyString : UnsafeCast<JSAny>(element); } LoadJoinElement<array::FastDoubleElements>( - context: Context, receiver: JSReceiver, k: Number): Object { + context: Context, receiver: JSReceiver, k: Number): JSAny { const array: JSArray = UnsafeCast<JSArray>(receiver); const fixedDoubleArray: FixedDoubleArray = UnsafeCast<FixedDoubleArray>(array.elements); @@ -51,7 +51,7 @@ namespace array_join { } builtin LoadJoinTypedElement<T: type>( - context: Context, receiver: JSReceiver, k: Number): Object { + context: Context, receiver: JSReceiver, k: Number): JSAny { const typedArray: JSTypedArray = UnsafeCast<JSTypedArray>(receiver); assert(!IsDetachedBuffer(typedArray.buffer)); return typed_array::LoadFixedTypedArrayElementAsTagged( @@ -60,14 +60,14 @@ namespace array_join { } transitioning builtin ConvertToLocaleString( - context: Context, element: Object, locales: Object, - options: Object): String { + context: Context, element: JSAny, locales: JSAny, + options: JSAny): String { if (IsNullOrUndefined(element)) return kEmptyString; - const prop: Object = GetProperty(element, 'toLocaleString'); + const prop: JSAny = GetProperty(element, 'toLocaleString'); try { const callable: Callable = Cast<Callable>(prop) otherwise TypeError; - let result: Object; + let result: JSAny; if (IsNullOrUndefined(locales)) { result = Call(context, callable, element); } else if (IsNullOrUndefined(options)) { @@ -86,29 +86,25 @@ namespace array_join { // (see LoadJoinElement<ElementsAccessor>). macro CannotUseSameArrayAccessor<T: type>(implicit context: Context)( loadFn: LoadJoinElementFn, receiver: JSReceiver, originalMap: Map, - originalLen: Number): never - labels Cannot, Can; + originalLen: Number): bool; CannotUseSameArrayAccessor<JSArray>(implicit context: Context)( loadFn: LoadJoinElementFn, receiver: JSReceiver, originalMap: Map, - originalLen: Number): never - labels Cannot, Can { - if (loadFn == LoadJoinElement<array::GenericElementsAccessor>) goto Can; + originalLen: Number): bool { + if (loadFn == LoadJoinElement<array::GenericElementsAccessor>) return false; const array: JSArray = UnsafeCast<JSArray>(receiver); - if (originalMap != array.map) goto Cannot; - if (originalLen != array.length) goto Cannot; - if (IsNoElementsProtectorCellInvalid()) goto Cannot; - goto Can; + if (originalMap != array.map) return true; + if (originalLen != array.length) return true; + if (IsNoElementsProtectorCellInvalid()) return true; + return false; } CannotUseSameArrayAccessor<JSTypedArray>(implicit context: Context)( _loadFn: LoadJoinElementFn, receiver: JSReceiver, _initialMap: Map, - _initialLen: Number): never - labels Cannot, Can { + _initialLen: Number): bool { const typedArray: JSTypedArray = UnsafeCast<JSTypedArray>(receiver); - if (IsDetachedBuffer(typedArray.buffer)) goto Cannot; - goto Can; + return IsDetachedBuffer(typedArray.buffer); } // Calculates the running total length of the resulting string. If the @@ -261,7 +257,7 @@ namespace array_join { transitioning macro ArrayJoinImpl<T: type>(implicit context: Context)( receiver: JSReceiver, sep: String, lengthNumber: Number, - useToLocaleString: constexpr bool, locales: Object, options: Object, + useToLocaleString: constexpr bool, locales: JSAny, options: JSAny, initialLoadFn: LoadJoinElementFn): String { const initialMap: Map = receiver.map; const len: uintptr = Convert<uintptr>(lengthNumber); @@ -287,7 +283,7 @@ namespace array_join { } // b. Let element be ? Get(O, ! ToString(k)). - const element: Object = loadFn(context, receiver, Convert<Number>(k++)); + const element: JSAny = loadFn(context, receiver, Convert<Number>(k++)); // c. If element is undefined or null, let next be the empty String; // otherwise, let next be ? ToString(element). @@ -304,7 +300,7 @@ namespace array_join { case (num: Number): { next = NumberToString(num); } - case (obj: HeapObject): { + case (obj: JSAny): { if (IsNullOrUndefined(obj)) continue; next = ToString(context, obj); } @@ -325,11 +321,11 @@ namespace array_join { transitioning macro ArrayJoin<T: type>(implicit context: Context)( useToLocaleString: constexpr bool, receiver: JSReceiver, sep: String, - lenNumber: Number, locales: Object, options: Object): Object; + lenNumber: Number, locales: JSAny, options: JSAny): JSAny; - ArrayJoin<JSArray>(implicit context: Context)( + transitioning ArrayJoin<JSArray>(implicit context: Context)( useToLocaleString: constexpr bool, receiver: JSReceiver, sep: String, - lenNumber: Number, locales: Object, options: Object): Object { + lenNumber: Number, locales: JSAny, options: JSAny): JSAny { const map: Map = receiver.map; const kind: ElementsKind = map.elements_kind; let loadFn: LoadJoinElementFn; @@ -374,9 +370,9 @@ namespace array_join { receiver, sep, lenNumber, useToLocaleString, locales, options, loadFn); } - ArrayJoin<JSTypedArray>(implicit context: Context)( + transitioning ArrayJoin<JSTypedArray>(implicit context: Context)( useToLocaleString: constexpr bool, receiver: JSReceiver, sep: String, - lenNumber: Number, locales: Object, options: Object): Object { + lenNumber: Number, locales: JSAny, options: JSAny): JSAny { const map: Map = receiver.map; const kind: ElementsKind = map.elements_kind; let loadFn: LoadJoinElementFn; @@ -465,11 +461,9 @@ namespace array_join { } // Fast path the common non-nested calls. If the receiver is not already on - // the stack, add it to the stack and go to ReceiverAdded. Otherwise go to - // ReceiverNotAdded. + // the stack, add it to the stack and return true. Otherwise return false. macro JoinStackPushInline(implicit context: Context)(receiver: JSReceiver): - never - labels ReceiverAdded, ReceiverNotAdded { + bool { try { const stack: FixedArray = LoadJoinStack() otherwise IfUninitialized; @@ -477,7 +471,7 @@ namespace array_join { stack.objects[0] = receiver; } else if (JoinStackPush(stack, receiver) == False) deferred { - goto ReceiverNotAdded; + return false; } } label IfUninitialized { @@ -486,13 +480,13 @@ namespace array_join { stack.objects[0] = receiver; SetJoinStack(stack); } - goto ReceiverAdded; + return true; } // Removes a receiver from the stack. The FixedArray will automatically shrink // to Heap::kMinJoinStackSize once the stack becomes empty. builtin JoinStackPop(implicit context: Context)( - stack: FixedArray, receiver: JSReceiver): Object { + stack: FixedArray, receiver: JSReceiver): JSAny { const len: intptr = stack.length_intptr; for (let i: intptr = 0; i < len; i++) { if (stack.objects[i] == receiver) { @@ -532,7 +526,7 @@ namespace array_join { transitioning macro CycleProtectedArrayJoin<T: type>(implicit context: Context)( useToLocaleString: constexpr bool, o: JSReceiver, len: Number, - sepObj: Object, locales: Object, options: Object): Object { + sepObj: JSAny, locales: JSAny, options: JSAny): JSAny { // 3. If separator is undefined, let sep be the single-element String ",". // 4. Else, let sep be ? ToString(separator). const sep: String = @@ -542,7 +536,7 @@ namespace array_join { // the normal join algorithm. if (len > 0 && JoinStackPushInline(o)) { try { - const result: Object = + const result: JSAny = ArrayJoin<T>(useToLocaleString, o, sep, len, locales, options); JoinStackPopInline(o); return result; @@ -557,9 +551,9 @@ namespace array_join { // https://tc39.github.io/ecma262/#sec-array.prototype.join transitioning javascript builtin - ArrayPrototypeJoin(js-implicit context: Context, receiver: Object)( - ...arguments): Object { - const separator: Object = arguments[0]; + ArrayPrototypeJoin(js-implicit context: Context, receiver: JSAny)( + ...arguments): JSAny { + const separator: JSAny = arguments[0]; // 1. Let O be ? ToObject(this value). const o: JSReceiver = ToObject_Inline(context, receiver); @@ -577,9 +571,9 @@ namespace array_join { // https://tc39.github.io/ecma262/#sec-array.prototype.tolocalestring transitioning javascript builtin ArrayPrototypeToLocaleString( - js-implicit context: Context, receiver: Object)(...arguments): Object { - const locales: Object = arguments[0]; - const options: Object = arguments[1]; + js-implicit context: Context, receiver: JSAny)(...arguments): JSAny { + const locales: JSAny = arguments[0]; + const options: JSAny = arguments[1]; // 1. Let O be ? ToObject(this value). const o: JSReceiver = ToObject_Inline(context, receiver); @@ -597,12 +591,12 @@ namespace array_join { // https://tc39.github.io/ecma262/#sec-array.prototype.tostring transitioning javascript builtin ArrayPrototypeToString( - js-implicit context: Context, receiver: Object)(...arguments): Object { + js-implicit context: Context, receiver: JSAny)(...arguments): JSAny { // 1. Let array be ? ToObject(this value). const array: JSReceiver = ToObject_Inline(context, receiver); // 2. Let func be ? Get(array, "join"). - const prop: Object = GetProperty(array, 'join'); + const prop: JSAny = GetProperty(array, 'join'); try { // 3. If IsCallable(func) is false, let func be the intrinsic function // %ObjProto_toString%. @@ -618,8 +612,8 @@ namespace array_join { // https://tc39.github.io/ecma262/#sec-%typedarray%.prototype.join transitioning javascript builtin TypedArrayPrototypeJoin( - js-implicit context: Context, receiver: Object)(...arguments): Object { - const separator: Object = arguments[0]; + js-implicit context: Context, receiver: JSAny)(...arguments): JSAny { + const separator: JSAny = arguments[0]; // Spec: ValidateTypedArray is applied to the this value prior to evaluating // the algorithm. @@ -633,9 +627,9 @@ namespace array_join { // https://tc39.github.io/ecma262/#sec-%typedarray%.prototype.tolocalestring transitioning javascript builtin TypedArrayPrototypeToLocaleString( - js-implicit context: Context, receiver: Object)(...arguments): Object { - const locales: Object = arguments[0]; - const options: Object = arguments[1]; + js-implicit context: Context, receiver: JSAny)(...arguments): JSAny { + const locales: JSAny = arguments[0]; + const options: JSAny = arguments[1]; // Spec: ValidateTypedArray is applied to the this value prior to evaluating // the algorithm. diff --git a/deps/v8/src/builtins/array-lastindexof.tq b/deps/v8/src/builtins/array-lastindexof.tq index 5ebc451e43..7765eff682 100644 --- a/deps/v8/src/builtins/array-lastindexof.tq +++ b/deps/v8/src/builtins/array-lastindexof.tq @@ -4,20 +4,20 @@ namespace array_lastindexof { macro LoadWithHoleCheck<Elements: type>( - elements: FixedArrayBase, index: Smi): Object + elements: FixedArrayBase, index: Smi): JSAny labels IfHole; LoadWithHoleCheck<FixedArray>(implicit context: Context)( - elements: FixedArrayBase, index: Smi): Object + elements: FixedArrayBase, index: Smi): JSAny labels IfHole { const elements: FixedArray = UnsafeCast<FixedArray>(elements); const element: Object = elements.objects[index]; if (element == TheHole) goto IfHole; - return element; + return UnsafeCast<JSAny>(element); } LoadWithHoleCheck<FixedDoubleArray>(implicit context: Context)( - elements: FixedArrayBase, index: Smi): Object + elements: FixedArrayBase, index: Smi): JSAny labels IfHole { const elements: FixedDoubleArray = UnsafeCast<FixedDoubleArray>(elements); const element: float64 = LoadDoubleWithHoleCheck(elements, index) @@ -26,7 +26,7 @@ namespace array_lastindexof { } macro FastArrayLastIndexOf<Elements: type>( - context: Context, array: JSArray, from: Smi, searchElement: Object): Smi { + context: Context, array: JSArray, from: Smi, searchElement: JSAny): Smi { const elements: FixedArrayBase = array.elements; let k: Smi = from; @@ -40,7 +40,7 @@ namespace array_lastindexof { while (k >= 0) { try { - const element: Object = LoadWithHoleCheck<Elements>(elements, k) + const element: JSAny = LoadWithHoleCheck<Elements>(elements, k) otherwise Hole; const same: Boolean = StrictEqual(searchElement, element); @@ -80,8 +80,8 @@ namespace array_lastindexof { } macro TryFastArrayLastIndexOf( - context: Context, receiver: JSReceiver, searchElement: Object, - from: Number): Object + context: Context, receiver: JSReceiver, searchElement: JSAny, + from: Number): JSAny labels Slow { const array: FastJSArray = Cast<FastJSArray>(receiver) otherwise Slow; const length: Smi = array.length; @@ -99,8 +99,8 @@ namespace array_lastindexof { } transitioning macro GenericArrayLastIndexOf( - context: Context, object: JSReceiver, searchElement: Object, - from: Number): Object { + context: Context, object: JSReceiver, searchElement: JSAny, + from: Number): JSAny { let k: Number = from; // 7. Repeat, while k >= 0. @@ -111,7 +111,7 @@ namespace array_lastindexof { // b. If kPresent is true, then. if (kPresent == True) { // i. Let elementK be ? Get(O, ! ToString(k)). - const element: Object = GetProperty(object, k); + const element: JSAny = GetProperty(object, k); // ii. Let same be the result of performing Strict Equality Comparison // searchElement === elementK. @@ -131,7 +131,7 @@ namespace array_lastindexof { // https://tc39.github.io/ecma262/#sec-array.prototype.lastIndexOf transitioning javascript builtin ArrayPrototypeLastIndexOf( - js-implicit context: Context, receiver: Object)(...arguments): Object { + js-implicit context: Context, receiver: JSAny)(...arguments): JSAny { // 1. Let O be ? ToObject(this value). const object: JSReceiver = ToObject_Inline(context, receiver); @@ -144,7 +144,7 @@ namespace array_lastindexof { // Step 4 - 6. const from: Number = GetFromIndex(context, length, arguments); - const searchElement: Object = arguments[0]; + const searchElement: JSAny = arguments[0]; try { return TryFastArrayLastIndexOf(context, object, searchElement, from) diff --git a/deps/v8/src/builtins/array-map.tq b/deps/v8/src/builtins/array-map.tq index dda569c682..c4b0e8a358 100644 --- a/deps/v8/src/builtins/array-map.tq +++ b/deps/v8/src/builtins/array-map.tq @@ -5,15 +5,15 @@ namespace array_map { transitioning javascript builtin ArrayMapLoopEagerDeoptContinuation( - js-implicit context: Context, receiver: Object)( - callback: Object, thisArg: Object, array: Object, initialK: Object, - length: Object): Object { + js-implicit context: Context, receiver: JSAny)( + callback: JSAny, thisArg: JSAny, array: JSAny, initialK: JSAny, + length: JSAny): JSAny { // All continuation points in the optimized filter implementation are // after the ToObject(O) call that ensures we are dealing with a // JSReceiver. // // Also, this great mass of casts is necessary because the signature - // of Torque javascript builtins requires Object type for all parameters + // of Torque javascript builtins requires JSAny type for all parameters // other than {context}. const jsreceiver = Cast<JSReceiver>(receiver) otherwise unreachable; const callbackfn = Cast<Callable>(callback) otherwise unreachable; @@ -28,9 +28,9 @@ namespace array_map { transitioning javascript builtin ArrayMapLoopLazyDeoptContinuation( - js-implicit context: Context, receiver: Object)( - callback: Object, thisArg: Object, array: Object, initialK: Object, - length: Object, result: Object): Object { + js-implicit context: Context, receiver: JSAny)( + callback: JSAny, thisArg: JSAny, array: JSAny, initialK: JSAny, + length: JSAny, result: JSAny): JSAny { // All continuation points in the optimized filter implementation are // after the ToObject(O) call that ensures we are dealing with a // JSReceiver. @@ -57,9 +57,9 @@ namespace array_map { } transitioning builtin ArrayMapLoopContinuation(implicit context: Context)( - _receiver: JSReceiver, callbackfn: Callable, thisArg: Object, + _receiver: JSReceiver, callbackfn: Callable, thisArg: JSAny, array: JSReceiver, o: JSReceiver, initialK: Number, - length: Number): Object { + length: Number): JSAny { // 6. Let k be 0. // 7. Repeat, while k < len for (let k: Number = initialK; k < length; k++) { @@ -73,10 +73,10 @@ namespace array_map { // 7c. If kPresent is true, then: if (kPresent == True) { // i. Let kValue be ? Get(O, Pk). - const kValue: Object = GetProperty(o, k); + const kValue: JSAny = GetProperty(o, k); // ii. Let mapped_value be ? Call(callbackfn, T, kValue, k, O). - const mappedValue: Object = + const mappedValue: JSAny = Call(context, callbackfn, thisArg, kValue, k, o); // iii. Perform ? CreateDataPropertyOrThrow(A, Pk, mapped_value). @@ -127,12 +127,12 @@ namespace array_map { SmiUntag(length), kAllowLargeObjectAllocation); a = NewJSArray(map, this.fixedArray); for (let i: Smi = 0; i < validLength; i++) { - typeswitch (this.fixedArray.objects[i]) { + typeswitch ( + UnsafeCast<(Number | TheHole)>(this.fixedArray.objects[i])) { case (n: Number): { elements.floats[i] = Convert<float64>(n); } - case (h: HeapObject): { - assert(h == TheHole); + case (TheHole): { } } } @@ -147,7 +147,7 @@ namespace array_map { return a; } - StoreResult(implicit context: Context)(index: Smi, result: Object) { + StoreResult(implicit context: Context)(index: Smi, result: JSAny) { typeswitch (result) { case (s: Smi): { this.fixedArray.objects[index] = s; @@ -156,7 +156,7 @@ namespace array_map { this.onlySmis = false; this.fixedArray.objects[index] = s; } - case (s: HeapObject): { + case (s: JSAnyNotNumber): { this.onlySmis = false; this.onlyNumbers = false; this.fixedArray.objects[index] = s; @@ -185,7 +185,7 @@ namespace array_map { transitioning macro FastArrayMap(implicit context: Context)( fastO: FastJSArrayForRead, len: Smi, callbackfn: Callable, - thisArg: Object): JSArray + thisArg: JSAny): JSArray labels Bailout(JSArray, Smi) { let k: Smi = 0; let fastOW = NewFastJSArrayForReadWitness(fastO); @@ -201,9 +201,9 @@ namespace array_map { if (k >= fastOW.Get().length) goto PrepareBailout(k); try { - const value: Object = fastOW.LoadElementNoHole(k) + const value: JSAny = fastOW.LoadElementNoHole(k) otherwise FoundHole; - const result: Object = + const result: JSAny = Call(context, callbackfn, thisArg, value, k, fastOW.Get()); vector.StoreResult(k, result); } @@ -224,8 +224,7 @@ namespace array_map { // https://tc39.github.io/ecma262/#sec-array.prototype.map transitioning javascript builtin - ArrayMap(js-implicit context: Context, receiver: Object)(...arguments): - Object { + ArrayMap(js-implicit context: Context, receiver: JSAny)(...arguments): JSAny { try { RequireObjectCoercible(receiver, 'Array.prototype.map'); @@ -241,7 +240,7 @@ namespace array_map { const callbackfn = Cast<Callable>(arguments[0]) otherwise TypeError; // 4. If thisArg is present, let T be thisArg; else let T be undefined. - const thisArg: Object = arguments.length > 1 ? arguments[1] : Undefined; + const thisArg: JSAny = arguments.length > 1 ? arguments[1] : Undefined; let array: JSReceiver; let k: Number = 0; diff --git a/deps/v8/src/builtins/array-of.tq b/deps/v8/src/builtins/array-of.tq index 7293318625..ceb9edff63 100644 --- a/deps/v8/src/builtins/array-of.tq +++ b/deps/v8/src/builtins/array-of.tq @@ -5,8 +5,7 @@ namespace array_of { // https://tc39.github.io/ecma262/#sec-array.of transitioning javascript builtin - ArrayOf(js-implicit context: Context, receiver: Object)(...arguments): - Object { + ArrayOf(js-implicit context: Context, receiver: JSAny)(...arguments): JSAny { // 1. Let len be the actual number of arguments passed to this function. const len: Smi = Convert<Smi>(arguments.length); @@ -14,7 +13,7 @@ namespace array_of { const items: Arguments = arguments; // 3. Let C be the this value. - const c: Object = receiver; + const c: JSAny = receiver; let a: JSReceiver; @@ -24,7 +23,7 @@ namespace array_of { // a. Let A be ? Construct(C, « len »). a = Construct(c, len); } - case (Object): { + case (JSAny): { // a. Let A be ? ArrayCreate(len). a = ArrayCreate(len); } @@ -36,7 +35,7 @@ namespace array_of { // 7. Repeat, while k < len while (k < len) { // a. Let kValue be items[k]. - const kValue: Object = items[Convert<intptr>(k)]; + const kValue: JSAny = items[Convert<intptr>(k)]; // b. Let Pk be ! ToString(k). // c. Perform ? CreateDataPropertyOrThrow(A, Pk, kValue). diff --git a/deps/v8/src/builtins/array-reduce-right.tq b/deps/v8/src/builtins/array-reduce-right.tq index b1aa71b85b..ae5ca99d3d 100644 --- a/deps/v8/src/builtins/array-reduce-right.tq +++ b/deps/v8/src/builtins/array-reduce-right.tq @@ -6,13 +6,13 @@ namespace array { transitioning javascript builtin ArrayReduceRightPreLoopEagerDeoptContinuation( js-implicit context: Context, - receiver: Object)(callback: Object, length: Object): Object { + receiver: JSAny)(callback: JSAny, length: JSAny): JSAny { // All continuation points in the optimized every implementation are // after the ToObject(O) call that ensures we are dealing with a // JSReceiver. // // Also, this great mass of casts is necessary because the signature - // of Torque javascript builtins requires Object type for all parameters + // of Torque javascript builtins requires JSAny type for all parameters // other than {context}. const jsreceiver = Cast<JSReceiver>(receiver) otherwise unreachable; const callbackfn = Cast<Callable>(callback) otherwise unreachable; @@ -27,15 +27,15 @@ namespace array { transitioning javascript builtin ArrayReduceRightLoopEagerDeoptContinuation( - js-implicit context: Context, receiver: Object)( - callback: Object, initialK: Object, length: Object, - accumulator: Object): Object { + js-implicit context: Context, receiver: JSAny)( + callback: JSAny, initialK: JSAny, length: JSAny, + accumulator: JSAny): JSAny { // All continuation points in the optimized every implementation are // after the ToObject(O) call that ensures we are dealing with a // JSReceiver. // // Also, this great mass of casts is necessary because the signature - // of Torque javascript builtins requires Object type for all parameters + // of Torque javascript builtins requires JSAny type for all parameters // other than {context}. const jsreceiver = Cast<JSReceiver>(receiver) otherwise unreachable; const callbackfn = Cast<Callable>(callback) otherwise unreachable; @@ -48,9 +48,8 @@ namespace array { transitioning javascript builtin ArrayReduceRightLoopLazyDeoptContinuation( - js-implicit context: Context, receiver: Object)( - callback: Object, initialK: Object, length: Object, - result: Object): Object { + js-implicit context: Context, receiver: JSAny)( + callback: JSAny, initialK: JSAny, length: JSAny, result: JSAny): JSAny { // All continuation points in the optimized every implementation are // after the ToObject(O) call that ensures we are dealing with a // JSReceiver. @@ -67,8 +66,9 @@ namespace array { transitioning builtin ArrayReduceRightLoopContinuation(implicit context: Context)( - _receiver: JSReceiver, callbackfn: Callable, initialAccumulator: Object, - o: JSReceiver, initialK: Number, _length: Number): Object { + _receiver: JSReceiver, callbackfn: Callable, + initialAccumulator: JSAny | TheHole, o: JSReceiver, initialK: Number, + _length: Number): JSAny { let accumulator = initialAccumulator; // 8b and 9. Repeat, while k >= 0 @@ -83,16 +83,20 @@ namespace array { // 8b iii and 9c. If kPresent is true, then if (present == True) { // 8b iii and 9c i. Let kValue be ? Get(O, Pk). - const value: Object = GetProperty(o, k); - - if (accumulator == TheHole) { - // 8b iii 1. - accumulator = value; - } else { - // 9c. ii. Set accumulator to ? Call(callbackfn, undefined, - // <accumulator, kValue, k, O>). - accumulator = - Call(context, callbackfn, Undefined, accumulator, value, k, o); + const value: JSAny = GetProperty(o, k); + + typeswitch (accumulator) { + case (TheHole): { + // 8b iii 1. + accumulator = value; + } + case (accumulatorNotHole: JSAny): { + // 9c. ii. Set accumulator to ? Call(callbackfn, undefined, + // <accumulator, kValue, k, O>). + accumulator = Call( + context, callbackfn, Undefined, accumulatorNotHole, value, k, + o); + } } } @@ -102,16 +106,20 @@ namespace array { // 8c. if kPresent is false, throw a TypeError exception. // If the accumulator is discovered with the sentinel hole value, // this means kPresent is false. - if (accumulator == TheHole) { - ThrowTypeError(kReduceNoInitial, 'Array.prototype.reduceRight'); + typeswitch (accumulator) { + case (TheHole): { + ThrowTypeError(kReduceNoInitial, 'Array.prototype.reduceRight'); + } + case (accumulator: JSAny): { + return accumulator; + } } - return accumulator; } transitioning macro FastArrayReduceRight(implicit context: Context)( o: JSReceiver, len: Number, callbackfn: Callable, - initialAccumulator: Object): Object - labels Bailout(Number, Object) { + initialAccumulator: JSAny | TheHole): JSAny + labels Bailout(Number, JSAny | TheHole) { let accumulator = initialAccumulator; const smiLen = Cast<Smi>(len) otherwise goto Bailout(len - 1, accumulator); const fastO = Cast<FastJSArrayForRead>(o) @@ -125,25 +133,32 @@ namespace array { // Ensure that we haven't walked beyond a possibly updated length. if (k >= fastOW.Get().length) goto Bailout(k, accumulator); - const value: Object = fastOW.LoadElementNoHole(k) otherwise continue; - if (accumulator == TheHole) { - accumulator = value; - } else { - accumulator = Call( - context, callbackfn, Undefined, accumulator, value, k, - fastOW.Get()); + const value: JSAny = fastOW.LoadElementNoHole(k) otherwise continue; + typeswitch (accumulator) { + case (TheHole): { + accumulator = value; + } + case (accumulatorNotHole: JSAny): { + accumulator = Call( + context, callbackfn, Undefined, accumulatorNotHole, value, k, + fastOW.Get()); + } } } - if (accumulator == TheHole) { - ThrowTypeError(kReduceNoInitial, 'Array.prototype.reduceRight'); + typeswitch (accumulator) { + case (TheHole): { + ThrowTypeError(kReduceNoInitial, 'Array.prototype.reduceRight'); + } + case (accumulator: JSAny): { + return accumulator; + } } - return accumulator; } // https://tc39.github.io/ecma262/#sec-array.prototype.reduceRight transitioning javascript builtin - ArrayReduceRight(js-implicit context: Context, receiver: Object)( - ...arguments): Object { + ArrayReduceRight(js-implicit context: Context, receiver: JSAny)(...arguments): + JSAny { try { RequireObjectCoercible(receiver, 'Array.prototype.reduceRight'); @@ -163,14 +178,14 @@ namespace array { // exception. (This case is handled at the end of // ArrayReduceRightLoopContinuation). - const initialValue: Object = + const initialValue: JSAny | TheHole = arguments.length > 1 ? arguments[1] : TheHole; try { return FastArrayReduceRight(o, len, callbackfn, initialValue) otherwise Bailout; } - label Bailout(value: Number, accumulator: Object) { + label Bailout(value: Number, accumulator: JSAny | TheHole) { return ArrayReduceRightLoopContinuation( o, callbackfn, accumulator, o, value, len); } diff --git a/deps/v8/src/builtins/array-reduce.tq b/deps/v8/src/builtins/array-reduce.tq index a5f6feb9cc..1021c48642 100644 --- a/deps/v8/src/builtins/array-reduce.tq +++ b/deps/v8/src/builtins/array-reduce.tq @@ -6,13 +6,13 @@ namespace array { transitioning javascript builtin ArrayReducePreLoopEagerDeoptContinuation( js-implicit context: Context, - receiver: Object)(callback: Object, length: Object): Object { + receiver: JSAny)(callback: JSAny, length: JSAny): JSAny { // All continuation points in the optimized every implementation are // after the ToObject(O) call that ensures we are dealing with a // JSReceiver. // // Also, this great mass of casts is necessary because the signature - // of Torque javascript builtins requires Object type for all parameters + // of Torque javascript builtins requires JSAny type for all parameters // other than {context}. const jsreceiver = Cast<JSReceiver>(receiver) otherwise unreachable; const callbackfn = Cast<Callable>(callback) otherwise unreachable; @@ -27,15 +27,15 @@ namespace array { transitioning javascript builtin ArrayReduceLoopEagerDeoptContinuation( - js-implicit context: Context, receiver: Object)( - callback: Object, initialK: Object, length: Object, - accumulator: Object): Object { + js-implicit context: Context, receiver: JSAny)( + callback: JSAny, initialK: JSAny, length: JSAny, + accumulator: JSAny): JSAny { // All continuation points in the optimized every implementation are // after the ToObject(O) call that ensures we are dealing with a // JSReceiver. // // Also, this great mass of casts is necessary because the signature - // of Torque javascript builtins requires Object type for all parameters + // of Torque javascript builtins requires JSAny type for all parameters // other than {context}. const jsreceiver = Cast<JSReceiver>(receiver) otherwise unreachable; const callbackfn = Cast<Callable>(callback) otherwise unreachable; @@ -48,9 +48,8 @@ namespace array { transitioning javascript builtin ArrayReduceLoopLazyDeoptContinuation( - js-implicit context: Context, receiver: Object)( - callback: Object, initialK: Object, length: Object, - result: Object): Object { + js-implicit context: Context, receiver: JSAny)( + callback: JSAny, initialK: JSAny, length: JSAny, result: JSAny): JSAny { // All continuation points in the optimized every implementation are // after the ToObject(O) call that ensures we are dealing with a // JSReceiver. @@ -66,8 +65,9 @@ namespace array { } transitioning builtin ArrayReduceLoopContinuation(implicit context: Context)( - _receiver: JSReceiver, callbackfn: Callable, initialAccumulator: Object, - o: JSReceiver, initialK: Number, length: Number): Object { + _receiver: JSReceiver, callbackfn: Callable, + initialAccumulator: JSAny | TheHole, o: JSReceiver, initialK: Number, + length: Number): JSAny { let accumulator = initialAccumulator; // 8b and 9. Repeat, while k < len @@ -82,16 +82,20 @@ namespace array { // 6c. If kPresent is true, then if (present == True) { // 6c. i. Let kValue be ? Get(O, Pk). - const value: Object = GetProperty(o, k); - - if (accumulator == TheHole) { - // 8b. - accumulator = value; - } else { - // 9c. ii. Set accumulator to ? Call(callbackfn, undefined, - // <accumulator, kValue, k, O>). - accumulator = - Call(context, callbackfn, Undefined, accumulator, value, k, o); + const value: JSAny = GetProperty(o, k); + + typeswitch (accumulator) { + case (TheHole): { + // 8b. + accumulator = value; + } + case (accumulatorNotHole: JSAny): { + // 9c. ii. Set accumulator to ? Call(callbackfn, undefined, + // <accumulator, kValue, k, O>). + accumulator = Call( + context, callbackfn, Undefined, accumulatorNotHole, value, k, + o); + } } } @@ -101,16 +105,20 @@ namespace array { // 8c. if kPresent is false, throw a TypeError exception. // If the accumulator is discovered with the sentinel hole value, // this means kPresent is false. - if (accumulator == TheHole) { - ThrowTypeError(kReduceNoInitial, 'Array.prototype.reduce'); + typeswitch (accumulator) { + case (TheHole): { + ThrowTypeError(kReduceNoInitial, 'Array.prototype.reduce'); + } + case (accumulator: JSAny): { + return accumulator; + } } - return accumulator; } transitioning macro FastArrayReduce(implicit context: Context)( o: JSReceiver, len: Number, callbackfn: Callable, - initialAccumulator: Object): Object - labels Bailout(Number, Object) { + initialAccumulator: JSAny | TheHole): JSAny + labels Bailout(Number, JSAny | TheHole) { const k = 0; let accumulator = initialAccumulator; Cast<Smi>(len) otherwise goto Bailout(k, accumulator); @@ -125,25 +133,32 @@ namespace array { // Ensure that we haven't walked beyond a possibly updated length. if (k >= fastOW.Get().length) goto Bailout(k, accumulator); - const value: Object = fastOW.LoadElementNoHole(k) otherwise continue; - if (accumulator == TheHole) { - accumulator = value; - } else { - accumulator = Call( - context, callbackfn, Undefined, accumulator, value, k, - fastOW.Get()); + const value: JSAny = fastOW.LoadElementNoHole(k) otherwise continue; + typeswitch (accumulator) { + case (TheHole): { + accumulator = value; + } + case (accumulatorNotHole: JSAny): { + accumulator = Call( + context, callbackfn, Undefined, accumulatorNotHole, value, k, + fastOW.Get()); + } } } - if (accumulator == TheHole) { - ThrowTypeError(kReduceNoInitial, 'Array.prototype.reduce'); + typeswitch (accumulator) { + case (TheHole): { + ThrowTypeError(kReduceNoInitial, 'Array.prototype.reduce'); + } + case (accumulator: JSAny): { + return accumulator; + } } - return accumulator; } // https://tc39.github.io/ecma262/#sec-array.prototype.reduce transitioning javascript builtin - ArrayReduce(js-implicit context: Context, receiver: Object)(...arguments): - Object { + ArrayReduce(js-implicit context: Context, receiver: JSAny)(...arguments): + JSAny { try { RequireObjectCoercible(receiver, 'Array.prototype.reduce'); @@ -163,14 +178,14 @@ namespace array { // exception. (This case is handled at the end of // ArrayReduceLoopContinuation). - const initialValue: Object = + const initialValue: JSAny | TheHole = arguments.length > 1 ? arguments[1] : TheHole; try { return FastArrayReduce(o, len, callbackfn, initialValue) otherwise Bailout; } - label Bailout(value: Number, accumulator: Object) { + label Bailout(value: Number, accumulator: JSAny | TheHole) { return ArrayReduceLoopContinuation( o, callbackfn, accumulator, o, value, len); } diff --git a/deps/v8/src/builtins/array-reverse.tq b/deps/v8/src/builtins/array-reverse.tq index 82d2e6b605..5e9d3a00f3 100644 --- a/deps/v8/src/builtins/array-reverse.tq +++ b/deps/v8/src/builtins/array-reverse.tq @@ -12,10 +12,10 @@ namespace array_reverse { return UnsafeCast<Smi>(elements.objects[index]); } - LoadElement<array::FastPackedObjectElements, Object>( - implicit context: Context)(elements: FixedArrayBase, index: Smi): Object { + LoadElement<array::FastPackedObjectElements, JSAny>( + implicit context: Context)(elements: FixedArrayBase, index: Smi): JSAny { const elements: FixedArray = UnsafeCast<FixedArray>(elements); - return elements.objects[index]; + return UnsafeCast<JSAny>(elements.objects[index]); } LoadElement<array::FastPackedDoubleElements, float64>( @@ -38,9 +38,9 @@ namespace array_reverse { StoreFixedArrayElement(elems, index, value, SKIP_WRITE_BARRIER); } - StoreElement<array::FastPackedObjectElements, Object>( + StoreElement<array::FastPackedObjectElements, JSAny>( implicit context: - Context)(elements: FixedArrayBase, index: Smi, value: Object) { + Context)(elements: FixedArrayBase, index: Smi, value: JSAny) { const elements: FixedArray = UnsafeCast<FixedArray>(elements); elements.objects[index] = value; } @@ -70,8 +70,8 @@ namespace array_reverse { } } - transitioning macro GenericArrayReverse(context: Context, receiver: Object): - Object { + transitioning macro GenericArrayReverse(context: Context, receiver: JSAny): + JSAny { // 1. Let O be ? ToObject(this value). const object: JSReceiver = ToObject_Inline(context, receiver); @@ -89,8 +89,8 @@ namespace array_reverse { let upper: Number = length - 1; while (lower < upper) { - let lowerValue: Object = Undefined; - let upperValue: Object = Undefined; + let lowerValue: JSAny = Undefined; + let upperValue: JSAny = Undefined; // b. Let upperP be ! ToString(upper). // c. Let lowerP be ! ToString(lower). @@ -142,7 +142,7 @@ namespace array_reverse { return object; } - macro TryFastPackedArrayReverse(implicit context: Context)(receiver: Object) + macro TryFastPackedArrayReverse(implicit context: Context)(receiver: JSAny) labels Slow { const array: FastJSArray = Cast<FastJSArray>(receiver) otherwise Slow; @@ -153,7 +153,7 @@ namespace array_reverse { array.elements, array.length); } else if (kind == PACKED_ELEMENTS) { array::EnsureWriteableFastElements(array); - FastPackedArrayReverse<array::FastPackedObjectElements, Object>( + FastPackedArrayReverse<array::FastPackedObjectElements, JSAny>( array.elements, array.length); } else if (kind == PACKED_DOUBLE_ELEMENTS) { FastPackedArrayReverse<array::FastPackedDoubleElements, float64>( @@ -165,7 +165,7 @@ namespace array_reverse { // https://tc39.github.io/ecma262/#sec-array.prototype.reverse transitioning javascript builtin ArrayPrototypeReverse( - js-implicit context: Context, receiver: Object)(...arguments): Object { + js-implicit context: Context, receiver: JSAny)(...arguments): JSAny { try { TryFastPackedArrayReverse(receiver) otherwise Baseline; return receiver; diff --git a/deps/v8/src/builtins/array-shift.tq b/deps/v8/src/builtins/array-shift.tq index 4dd82d7b88..48ffe3b487 100644 --- a/deps/v8/src/builtins/array-shift.tq +++ b/deps/v8/src/builtins/array-shift.tq @@ -3,11 +3,10 @@ // found in the LICENSE file. namespace array_shift { - extern builtin ArrayShift(Context, JSFunction, Object, int32); + extern builtin ArrayShift(Context, JSFunction, JSAny, int32): JSAny; - macro TryFastArrayShift(implicit context: Context)( - receiver: Object, arguments: Arguments): Object - labels Slow { + macro TryFastArrayShift(implicit context: Context)(receiver: JSAny): JSAny + labels Slow, Runtime { const array: FastJSArray = Cast<FastJSArray>(receiver) otherwise Slow; let witness = NewFastJSArrayWitness(array); @@ -17,35 +16,28 @@ namespace array_shift { return Undefined; } - try { - const newLength = array.length - 1; + 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 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; + // 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)); - } + const result = witness.LoadElementOrUndefined(0); + witness.ChangeLength(newLength); + witness.MoveElements(0, 1, Convert<intptr>(newLength)); + witness.StoreHole(newLength); + return result; } transitioning macro GenericArrayShift(implicit context: - Context)(receiver: Object): Object { + Context)(receiver: JSAny): JSAny { // 1. Let O be ? ToObject(this value). const object: JSReceiver = ToObject_Inline(context, receiver); @@ -78,7 +70,7 @@ namespace array_shift { // d. If fromPresent is true, then if (fromPresent == True) { // i. Let fromVal be ? Get(O, from). - const fromValue: Object = GetProperty(object, from); + const fromValue: JSAny = GetProperty(object, from); // ii. Perform ? Set(O, to, fromValue, true). SetProperty(object, to, fromValue); @@ -103,12 +95,17 @@ namespace array_shift { // https://tc39.github.io/ecma262/#sec-array.prototype.shift transitioning javascript builtin ArrayPrototypeShift( - js-implicit context: Context, receiver: Object)(...arguments): Object { + js-implicit context: Context, receiver: JSAny)(...arguments): JSAny { try { - return TryFastArrayShift(receiver, arguments) otherwise Slow; + return TryFastArrayShift(receiver) otherwise Slow, Runtime; } label Slow { return GenericArrayShift(receiver); } + label Runtime { + tail ArrayShift( + context, LoadTargetFromFrame(), Undefined, + Convert<int32>(arguments.length)); + } } } diff --git a/deps/v8/src/builtins/array-slice.tq b/deps/v8/src/builtins/array-slice.tq index c3a6ac75cb..57ddc8dea1 100644 --- a/deps/v8/src/builtins/array-slice.tq +++ b/deps/v8/src/builtins/array-slice.tq @@ -4,7 +4,7 @@ namespace array_slice { macro HandleSimpleArgumentsSlice( - context: Context, args: JSArgumentsObjectWithLength, start: Smi, + context: NativeContext, args: JSArgumentsObjectWithLength, start: Smi, count: Smi): JSArray labels Bailout { // If the resulting array doesn't fit in new space, use the slow path. @@ -27,7 +27,7 @@ namespace array_slice { } macro HandleFastAliasedSloppyArgumentsSlice( - context: Context, args: JSArgumentsObjectWithLength, start: Smi, + context: NativeContext, args: JSArgumentsObjectWithLength, start: Smi, count: Smi): JSArray labels Bailout { // If the resulting array doesn't fit in new space, use the slow path. @@ -63,9 +63,9 @@ namespace array_slice { for (let current: Smi = start; current < to; ++current) { const e: Object = sloppyElements.objects[current + kSloppyArgumentsParameterMapStart]; - const newElement: Object = e != TheHole ? - argumentsContext[UnsafeCast<Smi>(e)] : - unmappedElements.objects[current]; + const newElement: JSAny = UnsafeCast<JSAny>( + e != TheHole ? argumentsContext[UnsafeCast<Smi>(e)] : + unmappedElements.objects[current]); // It is safe to skip the write barrier here because resultElements was // allocated together with result in a folded allocation. // TODO(tebbi): The verification of this fails at the moment due to @@ -86,7 +86,7 @@ namespace array_slice { } macro HandleFastSlice( - context: Context, o: Object, startNumber: Number, + context: NativeContext, o: JSAny, startNumber: Number, countNumber: Number): JSArray labels Bailout { const start: Smi = Cast<Smi>(startNumber) otherwise Bailout; @@ -114,7 +114,7 @@ namespace array_slice { otherwise Bailout; } } - case (Object): { + case (JSAny): { } } goto Bailout; @@ -122,15 +122,15 @@ namespace array_slice { // https://tc39.github.io/ecma262/#sec-array.prototype.slice transitioning javascript builtin - ArrayPrototypeSlice(js-implicit context: Context, receiver: Object)( - ...arguments): Object { + ArrayPrototypeSlice(js-implicit context: Context, receiver: JSAny)( + ...arguments): JSAny { // Handle array cloning case if the receiver is a fast array. if (arguments.length == 0) { typeswitch (receiver) { case (a: FastJSArrayForCopy): { return CloneFastJSArray(context, a); } - case (Object): { + case (JSAny): { } } } @@ -142,7 +142,7 @@ namespace array_slice { const len: Number = GetLengthProperty(o); // 3. Let relativeStart be ? ToInteger(start). - const start: Object = arguments[0]; + const start: JSAny = arguments[0]; const relativeStart: Number = ToInteger_Inline(context, start); // 4. If relativeStart < 0, let k be max((len + relativeStart), 0); @@ -152,7 +152,7 @@ namespace array_slice { // 5. If end is undefined, let relativeEnd be len; // else let relativeEnd be ? ToInteger(end). - const end: Object = arguments[1]; + const end: JSAny = arguments[1]; const relativeEnd: Number = end == Undefined ? len : ToInteger_Inline(context, end); @@ -172,7 +172,8 @@ namespace array_slice { assert(count <= len); try { - return HandleFastSlice(context, o, k, count) otherwise Slow; + return HandleFastSlice(UnsafeCast<NativeContext>(context), o, k, count) + otherwise Slow; } label Slow {} @@ -193,7 +194,7 @@ namespace array_slice { // c. If kPresent is true, then if (fromPresent == True) { // i. Let kValue be ? Get(O, Pk). - const kValue: Object = GetProperty(o, pK); + const kValue: JSAny = GetProperty(o, pK); // ii. Perform ? CreateDataPropertyOrThrow(A, ! ToString(n), kValue). FastCreateDataProperty(a, n, kValue); diff --git a/deps/v8/src/builtins/array-some.tq b/deps/v8/src/builtins/array-some.tq index a30af4e47a..5d93dd0b72 100644 --- a/deps/v8/src/builtins/array-some.tq +++ b/deps/v8/src/builtins/array-some.tq @@ -5,15 +5,14 @@ namespace array { transitioning javascript builtin ArraySomeLoopEagerDeoptContinuation( - js-implicit context: Context, receiver: Object)( - callback: Object, thisArg: Object, initialK: Object, - length: Object): Object { + js-implicit context: Context, receiver: JSAny)( + callback: JSAny, thisArg: JSAny, initialK: JSAny, length: JSAny): JSAny { // All continuation points in the optimized some implementation are // after the ToObject(O) call that ensures we are dealing with a // JSReceiver. // // Also, this great mass of casts is necessary because the signature - // of Torque javascript builtins requires Object type for all parameters + // of Torque javascript builtins requires JSAny type for all parameters // other than {context}. const jsreceiver = Cast<JSReceiver>(receiver) otherwise unreachable; const callbackfn = Cast<Callable>(callback) otherwise unreachable; @@ -27,9 +26,9 @@ namespace array { transitioning javascript builtin ArraySomeLoopLazyDeoptContinuation( - js-implicit context: Context, receiver: Object)( - callback: Object, thisArg: Object, initialK: Object, length: Object, - result: Object): Object { + js-implicit context: Context, receiver: JSAny)( + callback: JSAny, thisArg: JSAny, initialK: JSAny, length: JSAny, + result: JSAny): JSAny { // All continuation points in the optimized some implementation are // after the ToObject(O) call that ensures we are dealing with a // JSReceiver. @@ -53,9 +52,9 @@ namespace array { } transitioning builtin ArraySomeLoopContinuation(implicit context: Context)( - _receiver: JSReceiver, callbackfn: Callable, thisArg: Object, - _array: Object, o: JSReceiver, initialK: Number, length: Number, - _initialTo: Object): Object { + _receiver: JSReceiver, callbackfn: Callable, thisArg: JSAny, + _array: JSAny, o: JSReceiver, initialK: Number, length: Number, + _initialTo: JSAny): JSAny { // 5. Let k be 0. // 6. Repeat, while k < len for (let k: Number = initialK; k < length; k++) { @@ -69,10 +68,10 @@ namespace array { // 6c. If kPresent is true, then if (kPresent == True) { // 6c. i. Let kValue be ? Get(O, Pk). - const kValue: Object = GetProperty(o, k); + const kValue: JSAny = GetProperty(o, k); // 6c. ii. Perform ? Call(callbackfn, T, <kValue, k, O>). - const result: Object = Call(context, callbackfn, thisArg, kValue, k, o); + const result: JSAny = Call(context, callbackfn, thisArg, kValue, k, o); // iii. If selected is true, then... if (ToBoolean(result)) { @@ -86,7 +85,7 @@ namespace array { } transitioning macro FastArraySome(implicit context: Context)( - o: JSReceiver, len: Number, callbackfn: Callable, thisArg: Object): Object + o: JSReceiver, len: Number, callbackfn: Callable, thisArg: JSAny): JSAny labels Bailout(Smi) { let k: Smi = 0; const smiLen = Cast<Smi>(len) otherwise goto Bailout(k); @@ -99,8 +98,8 @@ namespace array { // Ensure that we haven't walked beyond a possibly updated length. if (k >= fastOW.Get().length) goto Bailout(k); - const value: Object = fastOW.LoadElementNoHole(k) otherwise continue; - const result: Object = + const value: JSAny = fastOW.LoadElementNoHole(k) otherwise continue; + const result: JSAny = Call(context, callbackfn, thisArg, value, k, fastOW.Get()); if (ToBoolean(result)) { return True; @@ -111,8 +110,8 @@ namespace array { // https://tc39.github.io/ecma262/#sec-array.prototype.some transitioning javascript builtin - ArraySome(js-implicit context: Context, receiver: Object)(...arguments): - Object { + ArraySome(js-implicit context: Context, receiver: JSAny)(...arguments): + JSAny { try { RequireObjectCoercible(receiver, 'Array.prototype.some'); @@ -129,7 +128,7 @@ namespace array { const callbackfn = Cast<Callable>(arguments[0]) otherwise TypeError; // 4. If thisArg is present, let T be thisArg; else let T be undefined. - const thisArg: Object = arguments.length > 1 ? arguments[1] : Undefined; + const thisArg: JSAny = arguments.length > 1 ? arguments[1] : Undefined; // Special cases. try { diff --git a/deps/v8/src/builtins/array-splice.tq b/deps/v8/src/builtins/array-splice.tq index 3b65bb03d4..04885dbb9c 100644 --- a/deps/v8/src/builtins/array-splice.tq +++ b/deps/v8/src/builtins/array-splice.tq @@ -95,7 +95,7 @@ namespace array_splice { const typedNewElements: FixedArrayType = UnsafeCast<FixedArrayType>(a.elements); for (let i: intptr = 2; i < args.length; ++i) { - const e: Object = args[i]; + const e: JSAny = args[i]; // The argument elements were already validated to be an appropriate // {ElementType} to store in {FixedArrayType}. typedNewElements[k++] = UnsafeCast<ElementType>(e); @@ -109,7 +109,7 @@ namespace array_splice { transitioning macro FastArraySplice( context: Context, args: Arguments, o: JSReceiver, originalLengthNumber: Number, actualStartNumber: Number, insertCount: Smi, - actualDeleteCountNumber: Number): Object + actualDeleteCountNumber: Number): JSAny labels Bailout { const originalLength: Smi = Cast<Smi>(originalLengthNumber) otherwise Bailout; @@ -132,7 +132,7 @@ namespace array_splice { const oldElementsKind: ElementsKind = elementsKind; for (let i: intptr = 2; i < args.length; ++i) { - const e: Object = args[i]; + const e: JSAny = args[i]; if (IsFastSmiElementsKind(elementsKind)) { if (TaggedIsNotSmi(e)) { const heapObject: HeapObject = UnsafeCast<HeapObject>(e); @@ -166,7 +166,7 @@ namespace array_splice { } if (IsFastSmiOrTaggedElementsKind(elementsKind)) { - FastSplice<FixedArray, Object>( + FastSplice<FixedArray, JSAny>( args, a, length, newLength, actualStart, insertCount, actualDeleteCount); } else { @@ -180,7 +180,7 @@ namespace array_splice { transitioning macro FillDeletedElementsArray( context: Context, o: JSReceiver, actualStart: Number, - actualDeleteCount: Number, a: JSReceiver): Object { + actualDeleteCount: Number, a: JSReceiver): JSAny { // 10. Let k be 0. let k: Number = 0; @@ -195,7 +195,7 @@ namespace array_splice { // c. If fromPresent is true, then if (fromPresent == True) { // i. Let fromValue be ? Get(O, from). - const fromValue: Object = GetProperty(o, from); + const fromValue: JSAny = GetProperty(o, from); // ii. Perform ? CreateDataPropertyOrThrow(A, ! ToString(k), fromValue). FastCreateDataProperty(a, k, fromValue); @@ -231,7 +231,7 @@ namespace array_splice { // iv. If fromPresent is true, then if (fromPresent == True) { // 1. Let fromValue be ? Get(O, from). - const fromValue: Object = GetProperty(o, from); + const fromValue: JSAny = GetProperty(o, from); // 2. Perform ? Set(O, to, fromValue, true). SetProperty(o, to, fromValue); @@ -280,7 +280,7 @@ namespace array_splice { // iv. If fromPresent is true, then if (fromPresent == True) { // 1. Let fromValue be ? Get(O, from). - const fromValue: Object = GetProperty(o, from); + const fromValue: JSAny = GetProperty(o, from); // 2. Perform ? Set(O, to, fromValue, true). SetProperty(o, to, fromValue); @@ -298,8 +298,7 @@ namespace array_splice { transitioning macro SlowSplice( context: Context, arguments: Arguments, o: JSReceiver, len: Number, - actualStart: Number, insertCount: Smi, - actualDeleteCount: Number): Object { + actualStart: Number, insertCount: Smi, actualDeleteCount: Number): JSAny { // 9. Let A be ? ArraySpeciesCreate(O, actualDeleteCount). const a: JSReceiver = ArraySpeciesCreate(context, o, actualDeleteCount); const itemCount: Number = insertCount; @@ -332,7 +331,7 @@ namespace array_splice { // element. if (arguments.length > 2) { for (let i: intptr = 2; i < arguments.length; ++i) { - const e: Object = arguments[i]; + const e: JSAny = arguments[i]; // b. Perform ? Set(O, ! ToString(k), E, true). SetProperty(o, k, e); @@ -350,8 +349,8 @@ namespace array_splice { // https://tc39.github.io/ecma262/#sec-array.prototype.splice transitioning javascript builtin - ArrayPrototypeSplice(js-implicit context: Context, receiver: Object)( - ...arguments): Object { + ArrayPrototypeSplice(js-implicit context: Context, receiver: JSAny)( + ...arguments): JSAny { // 1. Let O be ? ToObject(this value). const o: JSReceiver = ToObject(context, receiver); @@ -359,7 +358,7 @@ namespace array_splice { const len: Number = GetLengthProperty(o); // 3. Let relativeStart be ? ToInteger(start). - const start: Object = arguments[0]; + const start: JSAny = arguments[0]; const relativeStart: Number = ToInteger_Inline(context, start); // 4. If relativeStart < 0, let actualStart be max((len + relativeStart), @@ -388,7 +387,7 @@ namespace array_splice { // a. Let insertCount be the Number of actual arguments minus 2. insertCount = Convert<Smi>(arguments.length) - 2; // b. Let dc be ? ToInteger(deleteCount). - const deleteCount: Object = arguments[1]; + const deleteCount: JSAny = arguments[1]; const dc: Number = ToInteger_Inline(context, deleteCount); // c. Let actualDeleteCount be min(max(dc, 0), len - actualStart). actualDeleteCount = Min(Max(dc, 0), len - actualStart); diff --git a/deps/v8/src/builtins/array-unshift.tq b/deps/v8/src/builtins/array-unshift.tq index e685d520cd..422eee158d 100644 --- a/deps/v8/src/builtins/array-unshift.tq +++ b/deps/v8/src/builtins/array-unshift.tq @@ -3,25 +3,10 @@ // found in the LICENSE file. namespace array_unshift { - extern builtin ArrayUnshift(Context, JSFunction, Object, int32); - - macro TryFastArrayUnshift( - context: Context, receiver: Object, arguments: Arguments): never - labels Slow { - const array: FastJSArray = Cast<FastJSArray>(receiver) otherwise Slow; - array::EnsureWriteableFastElements(array); - - const map: Map = array.map; - if (!IsExtensibleMap(map)) goto Slow; - EnsureArrayLengthWritable(map) otherwise Slow; - - tail ArrayUnshift( - context, LoadTargetFromFrame(), Undefined, - Convert<int32>(arguments.length)); - } + extern builtin ArrayUnshift(Context, JSFunction, JSAny, int32): JSAny; transitioning macro GenericArrayUnshift( - context: Context, receiver: Object, arguments: Arguments): Number { + context: Context, receiver: JSAny, arguments: Arguments): Number { // 1. Let O be ? ToObject(this value). const object: JSReceiver = ToObject_Inline(context, receiver); @@ -55,7 +40,7 @@ namespace array_unshift { // iv. If fromPresent is true, then if (fromPresent == True) { // 1. Let fromValue be ? Get(O, from). - const fromValue: Object = GetProperty(object, from); + const fromValue: JSAny = GetProperty(object, from); // 2. Perform ? Set(O, to, fromValue, true). SetProperty(object, to, fromValue); @@ -93,11 +78,20 @@ namespace array_unshift { // https://tc39.github.io/ecma262/#sec-array.prototype.unshift transitioning javascript builtin ArrayPrototypeUnshift( - js-implicit context: Context, receiver: Object)(...arguments): Object { + js-implicit context: Context, receiver: JSAny)(...arguments): JSAny { try { - TryFastArrayUnshift(context, receiver, arguments) otherwise Baseline; + const array: FastJSArray = Cast<FastJSArray>(receiver) otherwise Slow; + array::EnsureWriteableFastElements(array); + + const map: Map = array.map; + if (!IsExtensibleMap(map)) goto Slow; + EnsureArrayLengthWritable(map) otherwise Slow; + + tail ArrayUnshift( + context, LoadTargetFromFrame(), Undefined, + Convert<int32>(arguments.length)); } - label Baseline { + label Slow { return GenericArrayUnshift(context, receiver, arguments); } } diff --git a/deps/v8/src/builtins/array.tq b/deps/v8/src/builtins/array.tq index 7e044e086b..b9ae314c08 100644 --- a/deps/v8/src/builtins/array.tq +++ b/deps/v8/src/builtins/array.tq @@ -32,30 +32,15 @@ namespace array { assert(array.elements.map != kCOWMap); } - macro IsJSArray(implicit context: Context)(o: Object): bool { - typeswitch (o) { - case (JSArray): { - return true; - } - case (Object): { - return false; - } - } - } - - macro LoadElementOrUndefined(a: FixedArray, i: Smi): Object { - const e: Object = a.objects[i]; - return e == TheHole ? Undefined : e; + macro LoadElementOrUndefined(implicit context: + Context)(a: FixedArray, i: Smi): JSAny { + const e = UnsafeCast<(JSAny | TheHole)>(a.objects[i]); + return ReplaceTheHoleWithUndefined(e); } macro LoadElementOrUndefined(a: FixedDoubleArray, i: Smi): NumberOrUndefined { - try { - const f: float64 = LoadDoubleWithHoleCheck(a, i) otherwise IfHole; - return AllocateHeapNumberWithValue(f); - } - label IfHole { - return Undefined; - } + const f: float64 = LoadDoubleWithHoleCheck(a, i) otherwise return Undefined; + return AllocateHeapNumberWithValue(f); } macro StoreArrayHole(elements: FixedDoubleArray, k: Smi): void { @@ -66,5 +51,5 @@ namespace array { elements.objects[k] = TheHole; } - extern macro SetPropertyLength(implicit context: Context)(Object, Number); + extern macro SetPropertyLength(implicit context: Context)(JSAny, Number); } diff --git a/deps/v8/src/builtins/base.tq b/deps/v8/src/builtins/base.tq index 07af1f441f..aa5d4cc50a 100644 --- a/deps/v8/src/builtins/base.tq +++ b/deps/v8/src/builtins/base.tq @@ -43,6 +43,29 @@ extern class HeapObject extends Tagged { type Object = Smi | HeapObject; +// Defined to coincide with https://tc39.es/ecma262/#sec-ispropertykey +// Doesn't include PrivateSymbol. +type PropertyKey = String | PublicSymbol; + +// TODO(tebbi): PrivateSymbol is only exposed to JavaScript through the debugger +// API. We should reconsider this and try not to expose it at all. Then JSAny +// would not need to contain it. + +// A JavaScript primitive value as defined in +// https://tc39.es/ecma262/#sec-primitive-value. +type JSPrimitive = Numeric | String | Symbol | Boolean | + Null | Undefined; + +// A user-exposed JavaScript value, as opposed to V8-internal values like +// TheHole or FixedArray. +type JSAny = JSReceiver | JSPrimitive; + +type JSAnyNotNumber = BigInt | String | Symbol | Boolean | + Null | Undefined | JSReceiver; + +// This is the intersection of JSAny and HeapObject. +type JSAnyNotSmi = JSAnyNotNumber | HeapNumber; + type int32 generates 'TNode<Int32T>' constexpr 'int32_t'; type uint32 generates 'TNode<Uint32T>' constexpr 'uint32_t'; type int31 extends int32 @@ -56,6 +79,8 @@ type uint16 extends uint31 type int8 extends int16 generates 'TNode<Int8T>' constexpr 'int8_t'; type uint8 extends uint16 generates 'TNode<Uint8T>' constexpr 'uint8_t'; +type char8 extends int8 constexpr 'char'; +type char16 extends uint16 constexpr 'char16_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'; @@ -77,7 +102,7 @@ extern class Context extends HeapObject { extension: Object; native_context: Object; } -type NativeContext extends Context; +type NativeContext extends Context generates 'TNode<NativeContext>'; @generateCppClass extern class Oddball extends HeapObject { @@ -97,6 +122,9 @@ type Numeric = Number | BigInt; extern class Name extends HeapObject { hash_field: uint32; } +// This is the same as Name, but with the information that there are no other +// kinds of names. +type AnyName = PrivateSymbol | PublicSymbol | String; @generateCppClass extern class Symbol extends Name { @@ -104,6 +132,9 @@ extern class Symbol extends Name { name: Object; // The print name of a symbol, or undefined if none. } +type PublicSymbol extends Symbol; +type PrivateSymbol extends Symbol; + @abstract @generateCppClass extern class String extends Name { @@ -136,9 +167,11 @@ extern class SeqString extends String { } @generateCppClass extern class SeqOneByteString extends SeqString { + chars[length]: char8; } @generateCppClass extern class SeqTwoByteString extends SeqString { + chars[length]: char16; } @generateCppClass @@ -185,7 +218,6 @@ type DirectString extends String; type RootIndex generates 'TNode<Int32T>' constexpr 'RootIndex'; @abstract -@generateCppClass extern class FixedArrayBase extends HeapObject { length: Smi; } @@ -205,7 +237,7 @@ type LayoutDescriptor extends ByteArray type TransitionArray extends WeakFixedArray generates 'TNode<TransitionArray>'; -type InstanceType extends uint16 constexpr 'InstanceType'; +type InstanceType extends uint16 constexpr 'v8::internal::InstanceType'; extern class Map extends HeapObject { instance_size_in_words: uint8; @@ -388,8 +420,8 @@ extern class JSProxy extends JSReceiver { // Just a starting shape for JSObject; properties can move after initialization. @noVerifier extern class JSProxyRevocableResult extends JSObject { - proxy: Object; - revoke: Object; + proxy: JSAny; + revoke: JSAny; } macro NewJSProxyRevocableResult(implicit context: Context)( @@ -412,22 +444,24 @@ extern class JSGlobalProxy extends JSObject { @generateCppClass extern class JSPrimitiveWrapper extends JSObject { - value: Object; + value: JSAny; } -extern class JSArgumentsObject extends JSObject {} +@generateCppClass +extern class JSArgumentsObject extends JSObject { +} // Just a starting shape for JSObject; properties can move after initialization. @noVerifier @hasSameInstanceTypeAsParent extern class JSArgumentsObjectWithLength extends JSArgumentsObject { - length: Object; + length: JSAny; } // Just a starting shape for JSObject; properties can move after initialization. @hasSameInstanceTypeAsParent extern class JSSloppyArgumentsObject extends JSArgumentsObjectWithLength { - callee: Object; + callee: JSAny; } // Just a starting shape for JSObject; properties can move after initialization. @@ -492,8 +526,8 @@ type NoSharedNameSentinel extends Smi; @generateCppClass extern class CallHandlerInfo extends Struct { - callback: Foreign | Undefined; - js_callback: Foreign | Undefined; + callback: NonNullForeign | Undefined | Zero; + js_callback: NonNullForeign | Undefined | Zero; data: Object; } @@ -510,18 +544,37 @@ extern class Module extends HeapObject { type SourceTextModuleInfo extends FixedArray; +@generateCppClass extern class SourceTextModule extends Module { + // The code representing this module, or an abstraction thereof. code: SharedFunctionInfo | JSFunction | JSGeneratorObject | SourceTextModuleInfo; + + // Arrays of cells corresponding to regular exports and regular imports. + // A cell's position in the array is determined by the cell index of the + // associated module entry (which coincides with the variable index of the + // associated variable). regular_exports: FixedArray; regular_imports: FixedArray; + + // Modules imported or re-exported by this module. + // Corresponds 1-to-1 to the module specifier strings in + // SourceTextModuleInfo::module_requests. requested_modules: FixedArray; + + // Script from which the module originates. script: Script; + + // The value of import.meta inside of this module. + // Lazily initialized on first access. It's the hole before first access and + // a JSObject afterwards. import_meta: TheHole | JSObject; + dfs_index: Smi; dfs_ancestor_index: Smi; } +@generateCppClass extern class SyntheticModule extends Module { name: String; export_names: FixedArray; @@ -529,6 +582,7 @@ extern class SyntheticModule extends Module { } @abstract +@generateCppClass extern class JSModuleNamespace extends JSObject { module: Module; } @@ -539,14 +593,23 @@ extern class TemplateList extends FixedArray { } @abstract +@generateCppClass extern class JSWeakCollection extends JSObject { + // The backing hash table mapping keys to values. table: Object; } -extern class JSWeakSet extends JSWeakCollection {} -extern class JSWeakMap extends JSWeakCollection {} +@generateCppClass +extern class JSWeakSet extends JSWeakCollection { +} +@generateCppClass +extern class JSWeakMap extends JSWeakCollection { +} +@generateCppClass extern class JSCollectionIterator extends JSObject { + // The backing hash table mapping keys to values. table: Object; + // The index into the data table. index: Object; } @@ -601,7 +664,10 @@ extern class Script extends Struct { host_defined_options: Object; } -extern class EmbedderDataArray extends HeapObject { length: Smi; } +@generateCppClass +extern class EmbedderDataArray extends HeapObject { + length: Smi; +} type ScopeInfo extends HeapObject generates 'TNode<ScopeInfo>'; @@ -631,9 +697,15 @@ extern class SharedFunctionInfo extends HeapObject { @if(V8_SFI_HAS_UNIQUE_ID) unique_id: int32; } +@generateCppClass extern class JSBoundFunction extends JSObject { + // The wrapped function object. bound_target_function: Callable; - bound_this: Object; + // The value that is always passed as the this value when calling the wrapped + // function. + bound_this: JSAny; + // A list of values whose elements are used as the first arguments to any call + // to the wrapped function. bound_arguments: FixedArray; } @@ -644,7 +716,7 @@ extern class JSBoundFunction extends JSObject { type NonNullForeign extends Foreign; // A function built with InstantiateFunction for the public API. -type CallableApiObject extends HeapObject; +type CallableApiObject extends JSObject; // A JSProxy with the callable bit set. type CallableJSProxy extends JSProxy; @@ -729,14 +801,26 @@ extern class JSTypedArray extends JSArrayBufferView { } @abstract +@generateCppClass extern class JSCollection extends JSObject { + // The backing hash table. table: Object; } -extern class JSSet extends JSCollection {} -extern class JSMap extends JSCollection {} +@generateCppClass +extern class JSSet extends JSCollection { +} +@generateCppClass +extern class JSMap extends JSCollection { +} +@generateCppClass extern class JSDate extends JSObject { + // If one component is NaN, all of them are, indicating a NaN time value. + + // The time value. value: NumberOrUndefined; + + // Cached values: year: Undefined | Smi | NaN; month: Undefined | Smi | NaN; day: Undefined | Smi | NaN; @@ -744,6 +828,9 @@ extern class JSDate extends JSObject { hour: Undefined | Smi | NaN; min: Undefined | Smi | NaN; sec: Undefined | Smi | NaN; + + // Sample of the date cache stamp at the moment when chached fields were + // cached. cache_stamp: Undefined | Smi | NaN; } @@ -752,8 +839,11 @@ extern class JSGlobalObject extends JSObject { global_proxy: JSGlobalProxy; } +@generateCppClass extern class JSAsyncFromSyncIterator extends JSObject { sync_iterator: JSReceiver; + // The "next" method is loaded during GetIterator, and is not reloaded for + // subsequent "next" invocations. next: Object; } @@ -763,6 +853,7 @@ extern class JSStringIterator extends JSObject { } @abstract +@generateCppClass extern class TemplateInfo extends Struct { tag: Object; serial_number: Object; @@ -772,12 +863,15 @@ extern class TemplateInfo extends Struct { } @generatePrint +@generateCppClass extern class TemplateObjectDescription extends Struct { raw_strings: FixedArray; cooked_strings: FixedArray; } +@generateCppClass extern class FunctionTemplateRareData extends Struct { + // See DECL_RARE_ACCESSORS in FunctionTemplateInfo. prototype_template: Object; prototype_provider_template: Object; parent_template: Object; @@ -788,17 +882,31 @@ extern class FunctionTemplateRareData extends Struct { access_check_info: Object; } +@generateCppClass extern class FunctionTemplateInfo extends TemplateInfo { + // Handler invoked when calling an instance of this FunctionTemplateInfo. + // Either CallInfoHandler or Undefined. call_code: Object; class_name: Object; + // If the signature is a FunctionTemplateInfo it is used to check whether the + // receiver calling the associated JSFunction is a compatible receiver, i.e. + // it is an instance of the signature FunctionTemplateInfo or any of the + // receiver's prototypes are. signature: Object; - function_template_rare_data: Object; + // If any of the setters declared by DECL_RARE_ACCESSORS are used then a + // FunctionTemplateRareData will be stored here. Until then this contains + // undefined. + rare_data: HeapObject; shared_function_info: Object; flag: Smi; length: Smi; + // Either the_hole or a private symbol. Used to cache the result on + // the receiver under the the cached_property_name when this + // FunctionTemplateInfo is used as a getter. cached_property_name: Object; } +@generateCppClass extern class ObjectTemplateInfo extends TemplateInfo { constructor: Object; data: Object; @@ -809,7 +917,7 @@ extern class PropertyArray extends HeapObject { length_and_hash: Smi; } type DependentCode extends WeakFixedArray; extern class PropertyCell extends HeapObject { - name: Name; + name: AnyName; property_details_raw: Smi; value: Object; dependent_code: DependentCode; @@ -840,6 +948,7 @@ const UTF32: extern class Foreign extends HeapObject { foreign_address: RawPtr; } +@generateCppClass extern class InterceptorInfo extends Struct { getter: NonNullForeign | Zero | Undefined; setter: NonNullForeign | Zero | Undefined; @@ -852,6 +961,7 @@ extern class InterceptorInfo extends Struct { flags: Smi; } +@generateCppClass extern class AccessCheckInfo extends Struct { callback: Foreign | Zero | Undefined; named_interceptor: InterceptorInfo | Zero | Undefined; @@ -859,14 +969,21 @@ extern class AccessCheckInfo extends Struct { data: Object; } +@generateCppClass extern class ArrayBoilerplateDescription extends Struct { flags: Smi; constant_elements: FixedArrayBase; } -extern class AliasedArgumentsEntry extends Struct { aliased_context_slot: Smi; } +@generateCppClass +extern class AliasedArgumentsEntry extends Struct { + aliased_context_slot: Smi; +} -extern class Cell extends HeapObject { value: Object; } +@generateCppClass +extern class Cell extends HeapObject { + value: Object; +} extern class DataHandler extends Struct { smi_handler: Smi | Code; @@ -881,39 +998,58 @@ extern class DataHandler extends Struct { @abstract @dirtyInstantiatedAbstractClass +@generateCppClass extern class JSGeneratorObject extends JSObject { function: JSFunction; context: Context; - receiver: Object; + receiver: JSAny; + + // For executing generators: the most recent input value. + // For suspended generators: debug information (bytecode offset). + // There is currently no need to remember the most recent input value for a + // suspended generator. input_or_debug_pos: Object; + resume_mode: Smi; continuation: Smi; + + // Saved interpreter register file. parameters_and_registers: FixedArray; } +@generateCppClass extern class JSAsyncFunctionObject extends JSGeneratorObject { promise: JSPromise; } +@generateCppClass extern class JSAsyncGeneratorObject extends JSGeneratorObject { + // Pointer to the head of a singly linked list of AsyncGeneratorRequest, or + // undefined. queue: HeapObject; is_awaiting: Smi; } +@generateCppClass extern class JSPromise extends JSObject { + // Smi 0 terminated list of PromiseReaction objects in case the JSPromise was + // not settled yet, otherwise the result. reactions_or_result: Object; flags: Smi; } @abstract +@generateCppClass extern class Microtask extends Struct { } +@generateCppClass extern class CallbackTask extends Microtask { callback: Foreign; data: Foreign; } +@generateCppClass extern class CallableTask extends Microtask { callable: JSReceiver; context: Context; @@ -931,11 +1067,13 @@ extern class StackFrameInfo extends Struct { type_name: String | Null | Undefined; eval_origin: String | Null | Undefined; wasm_module_name: String | Null | Undefined; + wasm_instance: WasmInstanceObject | Null | Undefined; flag: Smi; } type FrameArray extends FixedArray; +@generateCppClass extern class StackTraceFrame extends Struct { frame_array: FrameArray | Undefined; frame_index: Smi; @@ -943,6 +1081,7 @@ extern class StackTraceFrame extends Struct { id: Smi; } +@generateCppClass extern class ClassPositions extends Struct { start: Smi; end: Smi; @@ -958,7 +1097,7 @@ extern class WasmExportedFunctionData extends Struct { // The remaining fields are for fast calling from C++. The contract is // that they are lazily populated, and either all will be present or none. c_wrapper_code: Object; - wasm_call_target: Smi; // Pseudo-smi: one-bit shift on all platforms. + wasm_call_target: Smi | Foreign; packed_args_size: Smi; } @@ -972,7 +1111,7 @@ extern class WasmJSFunctionData extends Struct { extern class WasmCapiFunctionData extends Struct { call_target: RawPtr; - embedder_data: RawPtr; + embedder_data: Foreign; // Managed<wasm::FuncData> wrapper_code: Code; serialized_signature: ByteArray; // PodArray<wasm::ValueType> } @@ -995,7 +1134,13 @@ extern class WasmDebugInfo extends Struct { c_wasm_entry_map: Foreign | Undefined; // Managed<wasm::SignatureMap> } -extern class WasmExceptionTag extends Struct { index: Smi; } +@generateCppClass +extern class WasmExceptionTag extends Struct { + index: Smi; +} + +const kTaggedSize: constexpr int31 generates 'kTaggedSize'; +const kDoubleSize: constexpr int31 generates 'kDoubleSize'; const kSmiTagSize: constexpr int31 generates 'kSmiTagSize'; const V8_INFINITY: constexpr float64 generates 'V8_INFINITY'; @@ -1013,8 +1158,8 @@ const PACKED_DOUBLE_ELEMENTS: constexpr ElementsKind generates 'PACKED_DOUBLE_ELEMENTS'; const HOLEY_DOUBLE_ELEMENTS: constexpr ElementsKind generates 'HOLEY_DOUBLE_ELEMENTS'; -const LAST_FROZEN_ELEMENTS_KIND: - constexpr ElementsKind generates 'LAST_FROZEN_ELEMENTS_KIND'; +const LAST_ANY_NONEXTENSIBLE_ELEMENTS_KIND: constexpr ElementsKind + generates 'LAST_ANY_NONEXTENSIBLE_ELEMENTS_KIND'; const DICTIONARY_ELEMENTS: constexpr ElementsKind generates 'DICTIONARY_ELEMENTS'; @@ -1186,6 +1331,7 @@ extern macro Int32FalseConstant(): bool; extern macro EmptyStringConstant(): EmptyString; extern macro LengthStringConstant(): String; extern macro NanConstant(): NaN; +extern macro IteratorSymbolConstant(): Symbol; const TheHole: TheHole = TheHoleConstant(); const Null: Null = NullConstant(); @@ -1207,6 +1353,7 @@ const SKIP_WRITE_BARRIER: const UNSAFE_SKIP_WRITE_BARRIER: constexpr WriteBarrierMode generates 'UNSAFE_SKIP_WRITE_BARRIER'; +@generateCppClass extern class AsyncGeneratorRequest extends Struct { next: AsyncGeneratorRequest | Undefined; resume_mode: Smi; @@ -1214,6 +1361,7 @@ extern class AsyncGeneratorRequest extends Struct { promise: JSPromise; } +@generateCppClass extern class SourceTextModuleInfoEntry extends Struct { export_name: String | Undefined; local_name: String | Undefined; @@ -1224,31 +1372,43 @@ extern class SourceTextModuleInfoEntry extends Struct { end_pos: Smi; } +@generateCppClass extern class PromiseCapability extends Struct { promise: JSReceiver | Undefined; resolve: Object; reject: Object; } +@generateCppClass extern class PromiseReaction extends Struct { next: PromiseReaction | Zero; reject_handler: Callable | Undefined; fulfill_handler: Callable | Undefined; + // Either a JSPromise (in case of native promises), a PromiseCapability + // (general case), or undefined (in case of await). promise_or_capability: JSPromise | PromiseCapability | Undefined; } @abstract +@generateCppClass extern class PromiseReactionJobTask extends Microtask { argument: Object; context: Context; handler: Callable | Undefined; + // Either a JSPromise (in case of native promises), a PromiseCapability + // (general case), or undefined (in case of await). promise_or_capability: JSPromise | PromiseCapability | Undefined; } -extern class PromiseFulfillReactionJobTask extends PromiseReactionJobTask {} +@generateCppClass +extern class PromiseFulfillReactionJobTask extends PromiseReactionJobTask { +} -extern class PromiseRejectReactionJobTask extends PromiseReactionJobTask {} +@generateCppClass +extern class PromiseRejectReactionJobTask extends PromiseReactionJobTask { +} +@generateCppClass extern class PromiseResolveThenableJobTask extends Microtask { context: Context; promise_to_resolve: JSPromise; @@ -1256,6 +1416,7 @@ extern class PromiseResolveThenableJobTask extends Microtask { thenable: JSReceiver; } +@generateCppClass extern class JSRegExp extends JSObject { data: FixedArray | Undefined; source: String | Undefined; @@ -1263,7 +1424,7 @@ extern class JSRegExp extends JSObject { } extern transitioning macro AllocateJSIteratorResult(implicit context: Context)( - Object, Boolean): JSObject; + JSAny, Boolean): JSObject; // Note: Although a condition for a FastJSRegExp is having a positive smi // lastIndex (see RegExpBuiltinsAssembler::BranchIfFastRegExp), it is possible @@ -1282,13 +1443,16 @@ RegExpBuiltinsAssembler::FastStoreLastIndex(FastJSRegExp, Smi): void; @hasSameInstanceTypeAsParent extern class JSRegExpResult extends JSArray { - index: Object; - input: Object; - groups: Object; + index: JSAny; + input: JSAny; + groups: JSAny; } +@generateCppClass extern class JSRegExpStringIterator extends JSObject { - iterating_reg_exp: Object; + // The [[IteratingRegExp]] internal property. + iterating_reg_exp: JSAny; + // The [[IteratedString]] internal property. iterated_string: String; flags: Smi; } @@ -1466,32 +1630,33 @@ extern macro Comment(constexpr string); extern macro StaticAssert(bool); extern macro Print(Object); extern macro DebugBreak(); -extern transitioning macro ToInteger_Inline(Context, Object): Number; +extern transitioning macro ToInteger_Inline(Context, JSAny): Number; extern transitioning macro ToInteger_Inline( - Context, Object, constexpr ToIntegerTruncationMode): Number; -extern transitioning macro ToLength_Inline(Context, Object): Number; -extern transitioning macro ToNumber_Inline(Context, Object): Number; -extern transitioning macro ToSmiIndex(implicit context: Context)(Object): + Context, JSAny, constexpr ToIntegerTruncationMode): Number; +extern transitioning macro ToLength_Inline(Context, JSAny): Number; +extern transitioning macro ToNumber_Inline(Context, JSAny): Number; +extern transitioning macro ToSmiIndex(implicit context: Context)(JSAny): PositiveSmi labels IfRangeError; -extern transitioning macro ToSmiLength(implicit context: Context)(Object): +extern transitioning macro ToSmiLength(implicit context: Context)(JSAny): PositiveSmi labels IfRangeError; -extern transitioning macro ToString_Inline(Context, Object): String; +extern transitioning macro ToString_Inline(Context, JSAny): String; extern transitioning macro ToThisString(implicit context: Context)( - Object, String): String; + JSAny, String): String; extern transitioning macro ToThisValue(implicit context: Context)( - Object, constexpr PrimitiveType, constexpr string): Object; + JSAny, constexpr PrimitiveType, constexpr string): JSAny; extern transitioning macro GetProperty(implicit context: Context)( - Object, Object): Object; + JSAny, JSAny): JSAny; extern transitioning builtin SetProperty(implicit context: Context)( - Object, Object, Object); + JSAny, JSAny, JSAny); extern transitioning builtin SetPropertyInLiteral(implicit context: Context)( - Object, Object, Object); + JSAny, JSAny, JSAny); extern transitioning builtin DeleteProperty(implicit context: Context)( - Object, Object, LanguageMode): Object; + JSAny, JSAny | PrivateSymbol, LanguageMode): Boolean; extern transitioning builtin HasProperty(implicit context: Context)( - Object, Object): Boolean; + JSAny, JSAny): Boolean; extern transitioning macro HasProperty_Inline(implicit context: Context)( - JSReceiver, Object): Boolean; + JSReceiver, JSAny): Boolean; +extern builtin LoadIC(Context, JSAny, JSAny, Smi, FeedbackVector): JSAny; extern macro ThrowRangeError(implicit context: Context)( constexpr MessageTemplate): never; @@ -1510,43 +1675,60 @@ extern macro ThrowTypeError(implicit context: Context)( extern transitioning runtime ThrowTypeErrorIfStrict(implicit context: Context)( Smi, Object, Object): void; -extern macro ArraySpeciesCreate(Context, Object, Number): JSReceiver; +extern transitioning macro ThrowIfNotJSReceiver(implicit context: Context)( + JSAny, constexpr MessageTemplate, constexpr string): void; + +extern macro ArraySpeciesCreate(Context, JSAny, Number): JSReceiver; extern macro ArrayCreate(implicit context: Context)(Number): JSArray; extern macro BuildAppendJSArray( - constexpr ElementsKind, FastJSArray, Object): void labels Bailout; + constexpr ElementsKind, FastJSArray, JSAny): void labels Bailout; extern macro EnsureArrayPushable(Map): ElementsKind labels Bailout; extern macro EnsureArrayLengthWritable(Map) labels Bailout; // TODO: Reduce duplication once varargs are supported in macros. extern macro Construct(implicit context: Context)( - Constructor, Object): JSReceiver; + Constructor, JSAny): JSReceiver; extern macro Construct(implicit context: Context)( - Constructor, Object, Object): JSReceiver; + Constructor, JSAny, JSAny): JSReceiver; extern macro Construct(implicit context: Context)( - Constructor, Object, Object, Object): JSReceiver; + Constructor, JSAny, JSAny, JSAny): JSReceiver; extern macro ConstructWithTarget(implicit context: Context)( Constructor, JSReceiver): JSReceiver; extern macro ConstructWithTarget(implicit context: Context)( - Constructor, JSReceiver, Object): JSReceiver; + Constructor, JSReceiver, JSAny): JSReceiver; extern macro SpeciesConstructor(implicit context: Context)( - Object, JSReceiver): JSReceiver; + JSAny, JSReceiver): JSReceiver; extern macro ConstructorBuiltinsAssembler::IsDictionaryMap(Map): bool; extern macro CodeStubAssembler::AllocateNameDictionary(constexpr int32): NameDictionary; -extern builtin ToObject(Context, Object): JSReceiver; -extern macro ToObject_Inline(Context, Object): JSReceiver; +extern builtin ToObject(Context, JSAny): JSReceiver; +extern macro ToObject_Inline(Context, JSAny): JSReceiver; extern macro IsNullOrUndefined(Object): bool; extern macro IsTheHole(Object): bool; extern macro IsString(HeapObject): bool; -transitioning builtin ToString(context: Context, o: Object): String { +transitioning builtin ToString(context: Context, o: JSAny): String { return ToStringImpl(context, o); } -extern transitioning runtime ToStringRT(Context, Object): String; +extern transitioning runtime ToStringRT(Context, JSAny): String; extern transitioning builtin NonPrimitiveToPrimitive_String( - Context, Object): Object; + Context, JSAny): JSPrimitive; +extern transitioning builtin NonPrimitiveToPrimitive_Default( + Context, JSAny): JSPrimitive; + +transitioning macro ToPrimitiveDefault(implicit context: Context)(v: JSAny): + JSPrimitive { + typeswitch (v) { + case (v: JSReceiver): { + return NonPrimitiveToPrimitive_Default(context, v); + } + case (v: JSPrimitive): { + return v; + } + } +} extern transitioning runtime NormalizeElements(Context, JSObject); extern transitioning runtime TransitionElementsKindWithKind( @@ -1556,18 +1738,15 @@ extern macro LoadBufferObject(RawPtr, constexpr int32): Object; extern macro LoadBufferPointer(RawPtr, constexpr int32): RawPtr; extern macro LoadBufferSmi(RawPtr, constexpr int32): Smi; -extern macro LoadRoot(constexpr RootIndex): Object; -extern macro StoreRoot(constexpr RootIndex, Object): Object; - extern runtime StringEqual(Context, String, String): Oddball; extern builtin StringLessThan(Context, String, String): Boolean; extern macro StringCharCodeAt(String, intptr): int32; extern runtime StringCompareSequence(Context, String, String, Number): Boolean; extern macro StringFromSingleCharCode(int32): String; -extern macro StrictEqual(Object, Object): Boolean; +extern macro StrictEqual(JSAny, JSAny): Boolean; extern macro SmiLexicographicCompare(Smi, Smi): Smi; -extern runtime ReThrow(Context, Object): never; +extern runtime ReThrow(Context, JSAny): never; extern runtime ThrowInvalidStringLength(Context): never; extern operator '==' macro WordEqual(RawPtr, RawPtr): bool; @@ -1638,38 +1817,51 @@ extern operator '<' macro Float64LessThan(float64, float64): bool; extern macro BranchIfNumberEqual(Number, Number): never labels Taken, NotTaken; operator '==' macro IsNumberEqual(a: Number, b: Number): bool { - return (BranchIfNumberEqual(a, b)) ? true : false; + BranchIfNumberEqual(a, b) otherwise return true, return false; } operator '!=' macro IsNumberNotEqual(a: Number, b: Number): bool { - return (BranchIfNumberEqual(a, b)) ? false : true; + return !(a == b); } -extern operator '<' macro BranchIfNumberLessThan(Number, Number): never +extern macro BranchIfNumberLessThan(Number, Number): never labels Taken, NotTaken; -extern operator '<=' macro BranchIfNumberLessThanOrEqual(Number, Number): never +operator '<' macro NumberIsLessThan(a: Number, b: Number): bool { + BranchIfNumberLessThan(a, b) otherwise return true, return false; +} +extern macro BranchIfNumberLessThanOrEqual(Number, Number): never labels Taken, NotTaken; +operator '<=' macro NumberIsLessThanOrEqual(a: Number, b: Number): bool { + BranchIfNumberLessThanOrEqual(a, b) otherwise return true, return false; +} -extern operator '>' macro BranchIfNumberGreaterThan(Number, Number): never - labels Taken, NotTaken; -extern operator '>=' macro BranchIfNumberGreaterThanOrEqual( - Number, Number): never +operator '>' macro NumberIsGreaterThan(a: Number, b: Number): bool { + return b < a; +} +operator '>=' macro NumberIsGreaterThanOrEqual(a: Number, b: Number): bool { + return b <= a; +} + +extern macro BranchIfFloat64IsNaN(float64): never labels Taken, NotTaken; +macro Float64IsNaN(n: float64): bool { + BranchIfFloat64IsNaN(n) otherwise return true, return false; +} -// The type of all tagged values that can safely be compared with WordEqual. +// The type of all tagged values that can safely be compared with TaggedEqual. type TaggedWithIdentity = JSReceiver | FixedArrayBase | Oddball | Map | EmptyString; -extern operator '==' macro WordEqual(TaggedWithIdentity, Object): bool; -extern operator '==' macro WordEqual(Object, TaggedWithIdentity): bool; -extern operator '==' macro WordEqual( +extern operator '==' macro TaggedEqual(TaggedWithIdentity, Object): bool; +extern operator '==' macro TaggedEqual(Object, TaggedWithIdentity): bool; +extern operator '==' macro TaggedEqual( TaggedWithIdentity, TaggedWithIdentity): bool; -extern operator '!=' macro WordNotEqual(TaggedWithIdentity, Object): bool; -extern operator '!=' macro WordNotEqual(Object, TaggedWithIdentity): bool; -extern operator '!=' macro WordNotEqual( +extern operator '!=' macro TaggedNotEqual(TaggedWithIdentity, Object): bool; +extern operator '!=' macro TaggedNotEqual(Object, TaggedWithIdentity): bool; +extern operator '!=' macro TaggedNotEqual( TaggedWithIdentity, TaggedWithIdentity): bool; // Do not overload == and != if it is unclear if object identity is the right // equality. -extern macro WordEqual(Object, Object): bool; -extern macro WordNotEqual(Object, Object): bool; +extern macro TaggedEqual(Object, Object): bool; +extern macro TaggedNotEqual(Object, Object): bool; extern operator '+' macro SmiAdd(Smi, Smi): Smi; extern operator '-' macro SmiSub(Smi, Smi): Smi; @@ -1707,11 +1899,14 @@ 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 Int32Div(int32, int32): int32; extern operator '%' macro Int32Mod(int32, int32): int32; extern operator '&' macro Word32And(int32, int32): int32; extern operator '&' macro Word32And(uint32, uint32): uint32; extern operator '==' macro ConstexprInt31Equal(constexpr int31, constexpr int31): constexpr bool; +extern operator '!=' macro +ConstexprInt31NotEqual(constexpr int31, constexpr int31): constexpr bool; extern operator '>=' macro ConstexprInt31GreaterThanEqual( constexpr int31, constexpr int31): constexpr bool; @@ -1732,6 +1927,8 @@ extern operator '!=' macro Word32NotEqual(bool, bool): bool; extern operator '+' macro Float64Add(float64, float64): float64; extern operator '-' macro Float64Sub(float64, float64): float64; +extern operator '*' macro Float64Mul(float64, float64): float64; +extern operator '/' macro Float64Div(float64, float64): float64; extern operator '+' macro NumberAdd(Number, Number): Number; extern operator '-' macro NumberSub(Number, Number): Number; @@ -1845,6 +2042,146 @@ Cast<Number>(o: Object): Number return TaggedToNumber(o) otherwise CastError; } +Cast<Undefined>(o: Object): Undefined + labels CastError { + if (o != Undefined) goto CastError; + return %RawDownCast<Undefined>(o); +} + +Cast<Numeric>(o: Object): Numeric labels CastError { + typeswitch (o) { + case (o: Number): { + return o; + } + case (o: BigInt): { + return o; + } + case (HeapObject): { + goto CastError; + } + } +} + +Cast<TheHole>(o: Object): TheHole labels CastError { + if (o == TheHole) return %RawDownCast<TheHole>(o); + goto CastError; +} + +Cast<TheHole>(o: HeapObject): TheHole labels CastError { + const o: Object = o; + return Cast<TheHole>(o) otherwise CastError; +} + +Cast<True>(o: Object): True labels CastError { + if (o == True) return %RawDownCast<True>(o); + goto CastError; +} + +Cast<True>(o: HeapObject): True labels CastError { + const o: Object = o; + return Cast<True>(o) otherwise CastError; +} + +Cast<False>(o: Object): False labels CastError { + if (o == False) return %RawDownCast<False>(o); + goto CastError; +} + +Cast<False>(o: HeapObject): False labels CastError { + const o: Object = o; + return Cast<False>(o) otherwise CastError; +} + +Cast<Boolean>(o: Object): Boolean labels CastError { + typeswitch (o) { + case (o: True): { + return o; + } + case (o: False): { + return o; + } + case (Object): { + goto CastError; + } + } +} + +Cast<Boolean>(o: HeapObject): Boolean labels CastError { + const o: Object = o; + return Cast<Boolean>(o) otherwise CastError; +} + +// TODO(tebbi): These trivial casts for union types should be generated +// automatically. + +Cast<JSPrimitive>(o: Object): JSPrimitive labels CastError { + typeswitch (o) { + case (o: Numeric): { + return o; + } + case (o: String): { + return o; + } + case (o: Symbol): { + return o; + } + case (o: Boolean): { + return o; + } + case (o: Undefined): { + return o; + } + case (o: Null): { + return o; + } + case (Object): { + goto CastError; + } + } +} + +Cast<JSAny>(o: Object): JSAny labels CastError { + typeswitch (o) { + case (o: JSPrimitive): { + return o; + } + case (o: JSReceiver): { + return o; + } + case (Object): { + goto CastError; + } + } +} + +Cast<JSAny | TheHole>(o: Object): JSAny | TheHole labels CastError { + typeswitch (o) { + case (o: JSAny): { + return o; + } + case (o: TheHole): { + return o; + } + case (Object): { + goto CastError; + } + } +} + +Cast<Number | TheHole>(o: Object): Number | TheHole labels CastError { + typeswitch (o) { + case (o: Number): { + return o; + } + case (o: TheHole): { + return o; + } + case (Object): { + goto CastError; + } + } +} + macro Cast<A: type>(o: HeapObject): A labels CastError; @@ -1859,6 +2196,12 @@ Cast<Null>(o: HeapObject): Null return %RawDownCast<Null>(o); } +Cast<Undefined>(o: HeapObject): Undefined + labels CastError { + const o: Object = o; + return Cast<Undefined>(o) otherwise CastError; +} + Cast<FixedArray>(o: HeapObject): FixedArray labels CastError { return HeapObjectToFixedArray(o) otherwise CastError; @@ -1928,6 +2271,12 @@ Cast<Context>(o: HeapObject): Context goto CastError; } +Cast<NativeContext>(o: HeapObject): NativeContext + labels CastError { + if (IsNativeContext(o)) return %RawDownCast<NativeContext>(o); + goto CastError; +} + Cast<JSObject>(o: HeapObject): JSObject labels CastError { if (IsJSObject(o)) return %RawDownCast<JSObject>(o); @@ -1957,6 +2306,27 @@ Cast<Symbol>(o: HeapObject): Symbol goto CastError; } +macro Cast<T: type>(o: Symbol): T labels CastError; +Cast<PublicSymbol>(o: Symbol): PublicSymbol labels CastError { + if (IsPrivateSymbol(o)) goto CastError; + return %RawDownCast<PublicSymbol>(o); +} +Cast<PrivateSymbol>(o: Symbol): PrivateSymbol labels CastError { + if (IsPrivateSymbol(o)) { + return %RawDownCast<PrivateSymbol>(o); + } + goto CastError; +} + +Cast<PublicSymbol>(o: HeapObject): PublicSymbol labels CastError { + const o = Cast<Symbol>(o) otherwise CastError; + return Cast<PublicSymbol>(o) otherwise CastError; +} +Cast<PrivateSymbol>(o: HeapObject): PrivateSymbol labels CastError { + const o = Cast<Symbol>(o) otherwise CastError; + return Cast<PrivateSymbol>(o) otherwise CastError; +} + Cast<DirectString>(o: HeapObject): DirectString labels CastError { return TaggedToDirectString(o) otherwise CastError; @@ -2014,7 +2384,13 @@ 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); + // TODO(jgruber): Remove or redesign this. There is no single 'fast' regexp, + // the conditions to make a regexp object fast differ based on the callsite. + // For now, run the strict variant since replace (the only current callsite) + // accesses flag getters. + if (regexp::IsFastRegExpStrict(o)) { + return %RawDownCast<FastJSRegExp>(o); + } goto CastError; } @@ -2042,7 +2418,8 @@ Cast<FastJSArrayForRead>(implicit context: Context)(o: HeapObject): // Bailout if receiver has slow elements. const elementsKind: ElementsKind = LoadMapElementsKind(map); - if (!IsElementsKindLessThanOrEqual(elementsKind, LAST_FROZEN_ELEMENTS_KIND)) + if (!IsElementsKindLessThanOrEqual( + elementsKind, LAST_ANY_NONEXTENSIBLE_ELEMENTS_KIND)) goto CastError; // Verify that our prototype is the initial array prototype. @@ -2076,7 +2453,7 @@ Cast<FastJSArrayForReadWithNoCustomIteration>(implicit context: Context)( return %RawDownCast<FastJSArrayForReadWithNoCustomIteration>(a); } -Cast<JSReceiver>(implicit context: Context)(o: HeapObject): JSReceiver +Cast<JSReceiver>(o: HeapObject): JSReceiver labels CastError { if (IsJSReceiver(o)) return %RawDownCast<JSReceiver>(o); goto CastError; @@ -2103,6 +2480,21 @@ Cast<CoverageInfo>(implicit context: Context)(o: HeapObject): CoverageInfo goto CastError; } +Cast<JSReceiver | Null>(o: HeapObject): JSReceiver | Null + labels CastError { + typeswitch (o) { + case (o: Null): { + return o; + } + case (o: JSReceiver): { + return o; + } + case (HeapObject): { + goto CastError; + } + } +} + extern macro AllocateHeapNumberWithValue(float64): HeapNumber; extern macro ChangeInt32ToTagged(int32): Number; extern macro ChangeUint32ToTagged(uint32): Number; @@ -2132,8 +2524,8 @@ extern macro ChangeUint32ToWord(uint32): uintptr; // Doesn't sign-extend. extern macro LoadNativeContext(Context): NativeContext; extern macro TruncateFloat64ToFloat32(float64): float32; extern macro TruncateHeapNumberValueToWord32(HeapNumber): int32; -extern macro LoadJSArrayElementsMap(constexpr ElementsKind, Context): Map; -extern macro LoadJSArrayElementsMap(ElementsKind, Context): Map; +extern macro LoadJSArrayElementsMap(constexpr ElementsKind, NativeContext): Map; +extern macro LoadJSArrayElementsMap(ElementsKind, NativeContext): Map; extern macro ChangeNonnegativeNumberToUintPtr(Number): uintptr; extern macro TryNumberToUintPtr(Number): uintptr labels IfNegative; extern macro NumberConstant(constexpr float64): Number; @@ -2157,6 +2549,7 @@ extern macro IntPtrConstant(constexpr ContextSlot): ContextSlot; extern macro IntPtrConstant(constexpr intptr): intptr; extern macro PointerConstant(constexpr RawPtr): RawPtr; extern macro SingleCharacterStringConstant(constexpr string): String; +extern macro Float64SilenceNaN(float64): float64; extern macro BitcastWordToTaggedSigned(intptr): Smi; extern macro BitcastWordToTaggedSigned(uintptr): Smi; @@ -2241,6 +2634,9 @@ FromConstexpr<ElementsKind, constexpr ElementsKind>(e: constexpr ElementsKind): FromConstexpr<Object, constexpr string>(s: constexpr string): Object { return StringConstant(s); } +FromConstexpr<JSAny, constexpr string>(s: constexpr string): JSAny { + return StringConstant(s); +} FromConstexpr<NativeContextSlot, constexpr NativeContextSlot>( c: constexpr NativeContextSlot): NativeContextSlot { return IntPtrConstant(c); @@ -2384,20 +2780,9 @@ Convert<bint, Smi>(v: Smi): bint { return SmiToBInt(v); } -macro BranchIf<A: type, B: type>(implicit context: Context)(o: B): never - labels True, False { - Cast<A>(o) otherwise False; - goto True; -} - -macro BranchIfNot<A: type, B: type>(implicit context: Context)(o: B): never - labels True, False { - Cast<A>(o) otherwise True; - goto False; -} - macro Is<A: type, B: type>(implicit context: Context)(o: B): bool { - return (BranchIf<A, B>(o)) ? true : false; + Cast<A>(o) otherwise return false; + return true; } macro UnsafeCast<A: type>(implicit context: Context)(o: Object): A { @@ -2405,17 +2790,15 @@ macro UnsafeCast<A: type>(implicit context: Context)(o: Object): A { return %RawDownCast<A>(o); } -UnsafeCast<Object>(o: Object): Object { - return o; -} +extern macro FixedArrayMapConstant(): Map; +extern macro FixedCOWArrayMapConstant(): Map; +extern macro EmptyByteArrayConstant(): ByteArray; +extern macro EmptyFixedArrayConstant(): FixedArray; -const kFixedArrayMap: Map = - %RawDownCast<Map>(LoadRoot(kFixedArrayMapRootIndex)); -const kCOWMap: Map = %RawDownCast<Map>(LoadRoot(kFixedCOWArrayMapRootIndex)); -const kEmptyByteArray: ByteArray = - %RawDownCast<ByteArray>(LoadRoot(kEmptyByteArrayRootIndex)); -const kEmptyFixedArray: FixedArray = - %RawDownCast<FixedArray>(LoadRoot(kEmptyFixedArrayRootIndex)); +const kFixedArrayMap: Map = FixedArrayMapConstant(); +const kCOWMap: Map = FixedCOWArrayMapConstant(); +const kEmptyByteArray: ByteArray = EmptyByteArrayConstant(); +const kEmptyFixedArray: FixedArray = EmptyFixedArrayConstant(); extern macro IsPrototypeInitialArrayPrototype(implicit context: Context)(Map): bool; @@ -2478,6 +2861,8 @@ extern operator '.floats[]=' macro StoreFixedDoubleArrayElement( FixedDoubleArray, intptr, float64): void; extern operator '.floats[]=' macro StoreFixedDoubleArrayElementSmi( FixedDoubleArray, Smi, float64): void; +extern operator '.floats[]' macro LoadFixedDoubleArrayElement( + FixedDoubleArray, intptr): float64; operator '[]=' macro StoreFixedDoubleArrayDirect( a: FixedDoubleArray, i: Smi, v: Number) { a.floats[i] = Convert<float64>(v); @@ -2487,14 +2872,14 @@ operator '[]=' macro StoreFixedArrayDirect(a: FixedArray, i: Smi, v: Object) { } extern macro GetNumberDictionaryNumberOfElements(NumberDictionary): Smi; -extern macro GetIteratorMethod(implicit context: Context)(HeapObject): Object +extern macro GetIteratorMethod(implicit context: Context)(HeapObject): JSAny labels IfIteratorUndefined; extern macro LoadConstructorOrBackPointer(Map): Object; -extern macro BasicLoadNumberDictionaryElement(NumberDictionary, intptr): Object +extern macro BasicLoadNumberDictionaryElement(NumberDictionary, intptr): JSAny labels NotData, IfHole; -extern macro BasicStoreNumberDictionaryElement(NumberDictionary, intptr, Object) +extern macro BasicStoreNumberDictionaryElement(NumberDictionary, intptr, JSAny) labels NotData, IfHole, ReadOnly; extern macro IsFastElementsKind(ElementsKind): bool; @@ -2607,16 +2992,15 @@ macro GetRegExpLastMatchInfo(implicit context: Context)(): RegExpMatchInfo { LoadNativeContext(context)[REGEXP_LAST_MATCH_INFO_INDEX]); } -extern transitioning macro Call(Context, Callable, Object): Object; -extern transitioning macro Call(Context, Callable, Object, Object): Object; -extern transitioning macro Call( - Context, Callable, Object, Object, Object): Object; +extern transitioning macro Call(Context, Callable, JSAny): JSAny; +extern transitioning macro Call(Context, Callable, JSAny, JSAny): JSAny; +extern transitioning macro Call(Context, Callable, JSAny, JSAny, JSAny): JSAny; extern transitioning macro Call( - Context, Callable, Object, Object, Object, Object): Object; + Context, Callable, JSAny, JSAny, JSAny, JSAny): JSAny; extern transitioning macro Call( - Context, Callable, Object, Object, Object, Object, Object): Object; + Context, Callable, JSAny, JSAny, JSAny, JSAny, JSAny): JSAny; extern transitioning macro Call( - Context, Callable, Object, Object, Object, Object, Object, Object): Object; + Context, Callable, JSAny, JSAny, JSAny, JSAny, JSAny, JSAny): JSAny; extern builtin CloneFastJSArray(Context, FastJSArrayForCopy): JSArray; extern macro ExtractFixedArray(FixedArrayBase, Smi, Smi, Smi): FixedArrayBase; @@ -2665,20 +3049,24 @@ macro TorqueCopyElements( count); } -macro LoadElementNoHole<T: type>(a: JSArray, index: Smi): Object +macro LoadElementNoHole<T: type>(a: JSArray, index: Smi): JSAny labels IfHole; LoadElementNoHole<FixedArray>(implicit context: Context)( - a: JSArray, index: Smi): Object + a: JSArray, index: Smi): JSAny labels IfHole { try { const elements: FixedArray = Cast<FixedArray>(a.elements) otherwise Unexpected; - const e: Object = elements.objects[index]; - if (e == TheHole) { - goto IfHole; + const e = UnsafeCast<(JSAny | TheHole)>(elements.objects[index]); + typeswitch (e) { + case (TheHole): { + goto IfHole; + } + case (e: JSAny): { + return e; + } } - return e; } label Unexpected { unreachable; @@ -2686,7 +3074,7 @@ LoadElementNoHole<FixedArray>(implicit context: Context)( } LoadElementNoHole<FixedDoubleArray>(implicit context: Context)( - a: JSArray, index: Smi): Object + a: JSArray, index: Smi): JSAny labels IfHole { try { const elements: FixedDoubleArray = @@ -2717,7 +3105,7 @@ struct FastJSArrayWitness { this.unstable = %RawDownCast<FastJSArray>(this.stable); } - LoadElementNoHole(implicit context: Context)(k: Smi): Object + LoadElementNoHole(implicit context: Context)(k: Smi): JSAny labels FoundHole { if (this.hasDoubles) { return LoadElementNoHole<FixedDoubleArray>(this.unstable, k) @@ -2740,7 +3128,7 @@ struct FastJSArrayWitness { } } - LoadElementOrUndefined(implicit context: Context)(k: Smi): Object { + LoadElementOrUndefined(implicit context: Context)(k: Smi): JSAny { try { return this.LoadElementNoHole(k) otherwise FoundHole; } @@ -2760,7 +3148,7 @@ struct FastJSArrayWitness { this.unstable.length = newLength; } - Push(value: Object) labels Failed { + Push(value: JSAny) labels Failed { assert(this.arrayIsPushable); if (this.hasDoubles) { BuildAppendJSArray(HOLEY_DOUBLE_ELEMENTS, this.unstable, value) @@ -2832,7 +3220,7 @@ struct FastJSArrayForReadWitness { this.unstable = %RawDownCast<FastJSArrayForRead>(this.stable); } - LoadElementNoHole(implicit context: Context)(k: Smi): Object + LoadElementNoHole(implicit context: Context)(k: Smi): JSAny labels FoundHole { if (this.hasDoubles) { return LoadElementNoHole<FixedDoubleArray>(this.unstable, k) @@ -2876,6 +3264,7 @@ extern macro IsJSObject(HeapObject): bool; extern macro IsJSTypedArray(HeapObject): bool; extern macro IsNumberDictionary(HeapObject): bool; extern macro IsContext(HeapObject): bool; +extern macro IsNativeContext(HeapObject): bool; extern macro IsJSReceiver(HeapObject): bool; extern macro TaggedIsCallable(Object): bool; extern macro IsDetachedBuffer(JSArrayBuffer): bool; @@ -2892,7 +3281,7 @@ extern macro IsJSArrayMap(Map): bool; extern macro IsExtensibleMap(Map): bool; extern macro IsJSPrimitiveWrapper(HeapObject): bool; extern macro IsCustomElementsReceiverInstanceType(int32): bool; -extern macro Typeof(Object): Object; +extern macro Typeof(JSAny): String; // Return true iff number is NaN. macro NumberIsNaN(number: Number): bool { @@ -2908,31 +3297,35 @@ macro NumberIsNaN(number: Number): bool { } extern macro GotoIfForceSlowPath() labels Taken; -extern macro BranchIfToBooleanIsTrue(Object): never +macro IsForceSlowPath(): bool { + GotoIfForceSlowPath() otherwise return true; + return false; +} + +extern macro BranchIfToBooleanIsTrue(JSAny): never labels Taken, NotTaken; -extern macro BranchIfToBooleanIsFalse(Object): never +extern macro BranchIfToBooleanIsFalse(JSAny): never labels Taken, NotTaken; -macro ToBoolean(obj: Object): bool { - if (BranchIfToBooleanIsTrue(obj)) { - return true; - } else { - return false; - } +macro ToBoolean(obj: JSAny): bool { + BranchIfToBooleanIsTrue(obj) otherwise return true, return false; } @export macro RequireObjectCoercible(implicit context: Context)( - value: Object, name: constexpr string): Object { + value: JSAny, name: constexpr string): JSAny { if (IsNullOrUndefined(value)) { ThrowTypeError(kCalledOnNullOrUndefined, name); } return value; } -extern macro BranchIfSameValue(Object, Object): never labels Taken, NotTaken; +extern macro BranchIfSameValue(JSAny, JSAny): never labels Taken, NotTaken; +macro SameValue(a: JSAny, b: JSAny): bool { + BranchIfSameValue(a, b) otherwise return true, return false; +} -transitioning macro ToIndex(input: Object, context: Context): Number +transitioning macro ToIndex(input: JSAny, context: Context): Number labels RangeError { if (input == Undefined) { return 0; @@ -2946,7 +3339,7 @@ transitioning macro ToIndex(input: Object, context: Context): Number return value; } -transitioning macro GetLengthProperty(implicit context: Context)(o: Object): +transitioning macro GetLengthProperty(implicit context: Context)(o: JSAny): Number { try { typeswitch (o) { @@ -2956,18 +3349,18 @@ transitioning macro GetLengthProperty(implicit context: Context)(o: Object): case (a: JSArgumentsObjectWithLength): { goto ToLength(a.length); } - case (Object): deferred { + case (JSAny): deferred { goto ToLength(GetProperty(o, kLengthString)); } } } - label ToLength(length: Object) deferred { + label ToLength(length: JSAny) deferred { return ToLength_Inline(context, length); } } transitioning macro GetMethod(implicit context: Context)( - o: Object, name: constexpr string): Callable labels IfNullOrUndefined { + o: JSAny, name: constexpr string): Callable labels IfNullOrUndefined { const value = GetProperty(o, name); if (value == Undefined || value == Null) goto IfNullOrUndefined; return Cast<Callable>(value) @@ -2976,44 +3369,37 @@ transitioning macro GetMethod(implicit context: Context)( extern macro NumberToString(Number): String; extern macro IsOneByteStringInstanceType(InstanceType): bool; -extern macro AllocateSeqOneByteString(implicit context: Context)(uint32): - String; -extern macro AllocateSeqTwoByteString(implicit context: Context)(uint32): - String; +extern macro AllocateSeqOneByteString(uint32): String; +extern macro AllocateSeqTwoByteString(uint32): String; extern macro ConvertToRelativeIndex(implicit context: Context)( - Object, intptr): intptr; + JSAny, intptr): intptr; -extern builtin ObjectToString(Context, Object): Object; +extern builtin ObjectToString(Context, JSAny): JSAny; extern builtin StringRepeat(Context, String, Number): String; struct KeyValuePair { - key: Object; - value: Object; + key: JSAny; + value: JSAny; } // Macro definitions for compatibility that expose functionality to the CSA // using "legacy" APIs. In Torque code, these should not be used. @export macro IsFastJSArray(o: Object, context: Context): bool { - try { - // Long-term, it's likely not a good idea to have this slow-path test here, - // since it fundamentally breaks the type system. - GotoIfForceSlowPath() otherwise ForceSlow; - } - label ForceSlow { - return false; - } - + // Long-term, it's likely not a good idea to have this slow-path test here, + // since it fundamentally breaks the type system. + if (IsForceSlowPath()) return false; return Is<FastJSArray>(o); } @export macro BranchIfFastJSArray(o: Object, context: Context): never labels True, False { - // Long-term, it's likely not a good idea to have this slow-path test here, - // since it fundamentally breaks the type system. - GotoIfForceSlowPath() otherwise False; - BranchIf<FastJSArray>(o) otherwise True, False; + if (IsFastJSArray(o, context)) { + goto True; + } else { + goto False; + } } @export @@ -3021,8 +3407,12 @@ macro BranchIfFastJSArrayForRead(o: Object, context: Context): never labels True, False { // Long-term, it's likely not a good idea to have this slow-path test here, // since it fundamentally breaks the type system. - GotoIfForceSlowPath() otherwise False; - BranchIf<FastJSArrayForRead>(o) otherwise True, False; + if (IsForceSlowPath()) goto False; + if (Is<FastJSArrayForRead>(o)) { + goto True; + } else { + goto False; + } } @export @@ -3037,7 +3427,7 @@ macro IsFastJSArrayForReadWithNoCustomIteration(context: Context, o: Object): } extern transitioning runtime -CreateDataProperty(implicit context: Context)(JSReceiver, Object, Object); +CreateDataProperty(implicit context: Context)(JSReceiver, JSAny, JSAny); namespace runtime { extern runtime @@ -3045,7 +3435,7 @@ namespace runtime { } transitioning builtin FastCreateDataProperty(implicit context: Context)( - receiver: JSReceiver, key: Object, value: Object): Object { + receiver: JSReceiver, key: JSAny, value: JSAny): Object { try { const array = Cast<FastJSArray>(receiver) otherwise Slow; const index: Smi = Cast<Smi>(key) otherwise goto Slow; @@ -3090,8 +3480,8 @@ transitioning builtin FastCreateDataProperty(implicit context: Context)( } @export -transitioning macro ToStringImpl(context: Context, o: Object): String { - let result: Object = o; +transitioning macro ToStringImpl(context: Context, o: JSAny): String { + let result: JSAny = o; while (true) { typeswitch (result) { case (num: Number): { @@ -3110,7 +3500,7 @@ transitioning macro ToStringImpl(context: Context, o: Object): String { case (Symbol): { ThrowTypeError(kSymbolToString); } - case (Object): { + case (JSAny): { return ToStringRT(context, o); } } @@ -3160,3 +3550,14 @@ builtin CheckNumberInRange(implicit context: Context)( unreachable; } } + +macro ReplaceTheHoleWithUndefined(o: JSAny | TheHole): JSAny { + typeswitch (o) { + case (TheHole): { + return Undefined; + } + case (a: JSAny): { + return a; + } + } +} diff --git a/deps/v8/src/builtins/boolean.tq b/deps/v8/src/builtins/boolean.tq index 25f9ebd396..e8feaf1cf1 100644 --- a/deps/v8/src/builtins/boolean.tq +++ b/deps/v8/src/builtins/boolean.tq @@ -5,8 +5,8 @@ namespace boolean { javascript builtin BooleanConstructor( - js-implicit context: Context, receiver: Object, newTarget: Object, - target: JSFunction)(...arguments): Object { + js-implicit context: Context, receiver: JSAny, newTarget: JSAny, + target: JSFunction)(...arguments): JSAny { const value = SelectBooleanConstant(ToBoolean(arguments[0])); if (newTarget == Undefined) { diff --git a/deps/v8/src/builtins/builtins-arguments-gen.cc b/deps/v8/src/builtins/builtins-arguments-gen.cc index d65d57cc79..c4399175e9 100644 --- a/deps/v8/src/builtins/builtins-arguments-gen.cc +++ b/deps/v8/src/builtins/builtins-arguments-gen.cc @@ -40,20 +40,20 @@ ArgumentsBuiltinsAssembler::AllocateArgumentsObject(Node* map, empty ? IntPtrConstant(base_size) : ElementOffsetFromIndex(element_count, PACKED_ELEMENTS, mode, base_size + FixedArray::kHeaderSize); - TNode<Object> result = Allocate(size); + TNode<HeapObject> result = Allocate(size); Comment("Initialize arguments object"); StoreMapNoWriteBarrier(result, map); - Node* empty_fixed_array = LoadRoot(RootIndex::kEmptyFixedArray); + TNode<FixedArray> empty_fixed_array = EmptyFixedArrayConstant(); StoreObjectField(result, JSArray::kPropertiesOrHashOffset, empty_fixed_array); - Node* smi_arguments_count = ParameterToTagged(arguments_count, mode); + TNode<Smi> smi_arguments_count = ParameterToTagged(arguments_count, mode); StoreObjectFieldNoWriteBarrier(result, JSArray::kLengthOffset, smi_arguments_count); Node* arguments = nullptr; if (!empty) { - arguments = InnerAllocate(CAST(result), elements_offset); + arguments = InnerAllocate(result, elements_offset); StoreObjectFieldNoWriteBarrier(arguments, FixedArray::kLengthOffset, smi_arguments_count); - Node* fixed_array_map = LoadRoot(RootIndex::kFixedArrayMap); + TNode<Map> fixed_array_map = FixedArrayMapConstant(); StoreMapNoWriteBarrier(arguments, fixed_array_map); } Node* parameter_map = nullptr; @@ -63,8 +63,7 @@ ArgumentsBuiltinsAssembler::AllocateArgumentsObject(Node* map, parameter_map = InnerAllocate(CAST(arguments), parameter_map_offset); StoreObjectFieldNoWriteBarrier(result, JSArray::kElementsOffset, parameter_map); - Node* sloppy_elements_map = - LoadRoot(RootIndex::kSloppyArgumentsElementsMap); + TNode<Map> sloppy_elements_map = SloppyArgumentsElementsMapConstant(); StoreMapNoWriteBarrier(parameter_map, sloppy_elements_map); parameter_map_count = ParameterToTagged(parameter_map_count, mode); StoreObjectFieldNoWriteBarrier(parameter_map, FixedArray::kLengthOffset, @@ -97,13 +96,14 @@ Node* ArgumentsBuiltinsAssembler::ConstructParametersObjectFromArgs( VARIABLE(offset, MachineType::PointerRepresentation()); offset.Bind(IntPtrConstant(FixedArrayBase::kHeaderSize - kHeapObjectTag)); VariableList list({&offset}, zone()); - arguments.ForEach(list, - [this, elements, &offset](Node* arg) { - StoreNoWriteBarrier(MachineRepresentation::kTagged, - elements, offset.value(), arg); - Increment(&offset, kTaggedSize); - }, - first_arg, nullptr, param_mode); + arguments.ForEach( + list, + [this, elements, &offset](Node* arg) { + StoreNoWriteBarrier(MachineRepresentation::kTagged, elements, + offset.value(), arg); + Increment(&offset, kTaggedSize); + }, + first_arg, nullptr, param_mode); return result; } @@ -121,8 +121,8 @@ Node* ArgumentsBuiltinsAssembler::EmitFastNewRestParameter(Node* context, Node* rest_count = IntPtrOrSmiSub(info.argument_count, info.formal_parameter_count, mode); - Node* const native_context = LoadNativeContext(context); - Node* const array_map = + TNode<NativeContext> const native_context = LoadNativeContext(context); + TNode<Map> const array_map = LoadJSArrayElementsMap(PACKED_ELEMENTS, native_context); GotoIf(IntPtrOrSmiLessThanOrEqual(rest_count, zero, mode), &no_rest_parameters); @@ -164,7 +164,7 @@ Node* ArgumentsBuiltinsAssembler::EmitFastNewStrictArguments(Node* context, Label done(this, &result), empty(this), runtime(this, Label::kDeferred); ParameterMode mode = OptimalParameterMode(); - Node* zero = IntPtrOrSmiConstant(0, mode); + TNode<BInt> zero = BIntConstant(0); TorqueStructArgumentsInfo info = GetArgumentsFrameAndCount( CAST(context), UncheckedCast<JSFunction>(function)); @@ -173,10 +173,10 @@ Node* ArgumentsBuiltinsAssembler::EmitFastNewStrictArguments(Node* context, info.argument_count, &runtime, JSStrictArgumentsObject::kSize + FixedArray::kHeaderSize, mode); - Node* const native_context = LoadNativeContext(context); - Node* const map = + TNode<NativeContext> const native_context = LoadNativeContext(context); + TNode<Object> const map = LoadContextElement(native_context, Context::STRICT_ARGUMENTS_MAP_INDEX); - GotoIf(WordEqual(info.argument_count, zero), &empty); + GotoIf(BIntEqual(info.argument_count, zero), &empty); result.Bind(ConstructParametersObjectFromArgs( map, info.frame, info.argument_count, zero, info.argument_count, mode, @@ -209,7 +209,7 @@ Node* ArgumentsBuiltinsAssembler::EmitFastNewSloppyArguments(Node* context, VARIABLE(result, MachineRepresentation::kTagged); ParameterMode mode = OptimalParameterMode(); - Node* zero = IntPtrOrSmiConstant(0, mode); + TNode<BInt> zero = BIntConstant(0); Label done(this, &result), empty(this), no_parameters(this), runtime(this, Label::kDeferred); @@ -217,9 +217,9 @@ Node* ArgumentsBuiltinsAssembler::EmitFastNewSloppyArguments(Node* context, TorqueStructArgumentsInfo info = GetArgumentsFrameAndCount( CAST(context), UncheckedCast<JSFunction>(function)); - GotoIf(WordEqual(info.argument_count, zero), &empty); + GotoIf(BIntEqual(info.argument_count, zero), &empty); - GotoIf(WordEqual(info.formal_parameter_count, zero), &no_parameters); + GotoIf(BIntEqual(info.formal_parameter_count, zero), &no_parameters); { Comment("Mapped parameter JSSloppyArgumentsObject"); @@ -237,8 +237,8 @@ Node* ArgumentsBuiltinsAssembler::EmitFastNewSloppyArguments(Node* context, elements_allocated, &runtime, JSSloppyArgumentsObject::kSize + FixedArray::kHeaderSize * 2, mode); - Node* const native_context = LoadNativeContext(context); - Node* const map = LoadContextElement( + TNode<NativeContext> const native_context = LoadNativeContext(context); + TNode<Object> const map = LoadContextElement( native_context, Context::FAST_ALIASED_ARGUMENTS_MAP_INDEX); Node* argument_object; Node* elements; @@ -252,26 +252,26 @@ Node* ArgumentsBuiltinsAssembler::EmitFastNewSloppyArguments(Node* context, StoreFixedArrayElement(CAST(map_array), 1, elements, SKIP_WRITE_BARRIER); Comment("Fill in non-mapped parameters"); - Node* argument_offset = + TNode<IntPtrT> argument_offset = ElementOffsetFromIndex(info.argument_count, PACKED_ELEMENTS, mode, FixedArray::kHeaderSize - kHeapObjectTag); - Node* mapped_offset = + TNode<IntPtrT> mapped_offset = ElementOffsetFromIndex(mapped_count, PACKED_ELEMENTS, mode, FixedArray::kHeaderSize - kHeapObjectTag); CodeStubArguments arguments(this, info.argument_count, info.frame, mode); VARIABLE(current_argument, MachineType::PointerRepresentation()); current_argument.Bind(arguments.AtIndexPtr(info.argument_count, mode)); VariableList var_list1({¤t_argument}, zone()); - mapped_offset = BuildFastLoop( + mapped_offset = UncheckedCast<IntPtrT>(BuildFastLoop( var_list1, argument_offset, mapped_offset, [this, elements, ¤t_argument](Node* offset) { Increment(¤t_argument, kSystemPointerSize); - Node* arg = LoadBufferObject( + TNode<Object> arg = LoadBufferObject( UncheckedCast<RawPtrT>(current_argument.value()), 0); StoreNoWriteBarrier(MachineRepresentation::kTagged, elements, offset, arg); }, - -kTaggedSize, INTPTR_PARAMETERS); + -kTaggedSize, INTPTR_PARAMETERS)); // Copy the parameter slots and the holes in the arguments. // We need to fill in mapped_count slots. They index the context, @@ -287,13 +287,13 @@ Node* ArgumentsBuiltinsAssembler::EmitFastNewSloppyArguments(Node* context, IntPtrOrSmiAdd(IntPtrOrSmiConstant(Context::MIN_CONTEXT_SLOTS, mode), info.formal_parameter_count, mode), mapped_count, mode)); - Node* the_hole = TheHoleConstant(); + TNode<Oddball> the_hole = TheHoleConstant(); VariableList var_list2({&context_index}, zone()); const int kParameterMapHeaderSize = FixedArray::OffsetOfElementAt(2); - Node* adjusted_map_array = IntPtrAdd( + TNode<IntPtrT> adjusted_map_array = IntPtrAdd( BitcastTaggedToWord(map_array), IntPtrConstant(kParameterMapHeaderSize - FixedArray::kHeaderSize)); - Node* zero_offset = ElementOffsetFromIndex( + TNode<IntPtrT> zero_offset = ElementOffsetFromIndex( zero, PACKED_ELEMENTS, mode, FixedArray::kHeaderSize - kHeapObjectTag); BuildFastLoop( var_list2, mapped_offset, zero_offset, @@ -317,8 +317,8 @@ Node* ArgumentsBuiltinsAssembler::EmitFastNewSloppyArguments(Node* context, GotoIfFixedArraySizeDoesntFitInNewSpace( info.argument_count, &runtime, JSSloppyArgumentsObject::kSize + FixedArray::kHeaderSize, mode); - Node* const native_context = LoadNativeContext(context); - Node* const map = + TNode<NativeContext> const native_context = LoadNativeContext(context); + TNode<Object> const map = LoadContextElement(native_context, Context::SLOPPY_ARGUMENTS_MAP_INDEX); result.Bind(ConstructParametersObjectFromArgs( map, info.frame, info.argument_count, zero, info.argument_count, mode, @@ -331,8 +331,8 @@ Node* ArgumentsBuiltinsAssembler::EmitFastNewSloppyArguments(Node* context, BIND(&empty); { Comment("Empty JSSloppyArgumentsObject"); - Node* const native_context = LoadNativeContext(context); - Node* const map = + TNode<NativeContext> const native_context = LoadNativeContext(context); + TNode<Object> const map = LoadContextElement(native_context, Context::SLOPPY_ARGUMENTS_MAP_INDEX); Node* arguments; Node* elements; diff --git a/deps/v8/src/builtins/builtins-array-gen.cc b/deps/v8/src/builtins/builtins-array-gen.cc index 07f74cb429..c7d8eb0091 100644 --- a/deps/v8/src/builtins/builtins-array-gen.cc +++ b/deps/v8/src/builtins/builtins-array-gen.cc @@ -30,272 +30,267 @@ ArrayBuiltinsAssembler::ArrayBuiltinsAssembler( to_(this, MachineRepresentation::kTagged, SmiConstant(0)), fully_spec_compliant_(this, {&k_, &a_, &to_}) {} - void ArrayBuiltinsAssembler::TypedArrayMapResultGenerator() { - // 6. Let A be ? TypedArraySpeciesCreate(O, len). - TNode<JSTypedArray> original_array = CAST(o()); - TNode<Smi> length = CAST(len_); - const char* method_name = "%TypedArray%.prototype.map"; - - TNode<JSTypedArray> a = TypedArraySpeciesCreateByLength( - context(), method_name, original_array, length); - // In the Spec and our current implementation, the length check is already - // performed in TypedArraySpeciesCreate. - CSA_ASSERT(this, UintPtrLessThanOrEqual(SmiUntag(CAST(len_)), - LoadJSTypedArrayLength(a))); - fast_typed_array_target_ = - Word32Equal(LoadElementsKind(original_array), LoadElementsKind(a)); - a_.Bind(a); - } - - // See tc39.github.io/ecma262/#sec-%typedarray%.prototype.map. - Node* ArrayBuiltinsAssembler::TypedArrayMapProcessor(Node* k_value, Node* k) { - // 8. c. Let mapped_value be ? Call(callbackfn, T, « kValue, k, O »). - Node* mapped_value = CallJS(CodeFactory::Call(isolate()), context(), - callbackfn(), this_arg(), k_value, k, o()); - Label fast(this), slow(this), done(this), detached(this, Label::kDeferred); - - // 8. d. Perform ? Set(A, Pk, mapped_value, true). - // Since we know that A is a TypedArray, this always ends up in - // #sec-integer-indexed-exotic-objects-set-p-v-receiver and then - // tc39.github.io/ecma262/#sec-integerindexedelementset . - Branch(fast_typed_array_target_, &fast, &slow); - - BIND(&fast); - // #sec-integerindexedelementset - // 5. If arrayTypeName is "BigUint64Array" or "BigInt64Array", let - // numValue be ? ToBigInt(v). - // 6. Otherwise, let numValue be ? ToNumber(value). - Node* num_value; - if (source_elements_kind_ == BIGINT64_ELEMENTS || - source_elements_kind_ == BIGUINT64_ELEMENTS) { - num_value = ToBigInt(context(), mapped_value); - } else { - num_value = ToNumber_Inline(context(), mapped_value); - } - // The only way how this can bailout is because of a detached buffer. - EmitElementStore(a(), k, num_value, source_elements_kind_, - KeyedAccessStoreMode::STANDARD_STORE, &detached, - context()); - Goto(&done); +void ArrayBuiltinsAssembler::TypedArrayMapResultGenerator() { + // 6. Let A be ? TypedArraySpeciesCreate(O, len). + TNode<JSTypedArray> original_array = CAST(o()); + TNode<Smi> length = CAST(len_); + const char* method_name = "%TypedArray%.prototype.map"; + + TNode<JSTypedArray> a = TypedArraySpeciesCreateByLength( + context(), method_name, original_array, length); + // In the Spec and our current implementation, the length check is already + // performed in TypedArraySpeciesCreate. + CSA_ASSERT(this, UintPtrLessThanOrEqual(SmiUntag(CAST(len_)), + LoadJSTypedArrayLength(a))); + fast_typed_array_target_ = + Word32Equal(LoadElementsKind(original_array), LoadElementsKind(a)); + a_.Bind(a); +} - BIND(&slow); - SetPropertyStrict(context(), CAST(a()), CAST(k), CAST(mapped_value)); - Goto(&done); +// See tc39.github.io/ecma262/#sec-%typedarray%.prototype.map. +Node* ArrayBuiltinsAssembler::TypedArrayMapProcessor(Node* k_value, Node* k) { + // 8. c. Let mapped_value be ? Call(callbackfn, T, « kValue, k, O »). + Node* mapped_value = CallJS(CodeFactory::Call(isolate()), context(), + callbackfn(), this_arg(), k_value, k, o()); + Label fast(this), slow(this), done(this), detached(this, Label::kDeferred); - BIND(&detached); - // tc39.github.io/ecma262/#sec-integerindexedelementset - // 8. If IsDetachedBuffer(buffer) is true, throw a TypeError exception. - ThrowTypeError(context_, MessageTemplate::kDetachedOperation, name_); + // 8. d. Perform ? Set(A, Pk, mapped_value, true). + // Since we know that A is a TypedArray, this always ends up in + // #sec-integer-indexed-exotic-objects-set-p-v-receiver and then + // tc39.github.io/ecma262/#sec-integerindexedelementset . + Branch(fast_typed_array_target_, &fast, &slow); - BIND(&done); - return a(); + BIND(&fast); + // #sec-integerindexedelementset + // 5. If arrayTypeName is "BigUint64Array" or "BigInt64Array", let + // numValue be ? ToBigInt(v). + // 6. Otherwise, let numValue be ? ToNumber(value). + Node* num_value; + if (source_elements_kind_ == BIGINT64_ELEMENTS || + source_elements_kind_ == BIGUINT64_ELEMENTS) { + num_value = ToBigInt(context(), mapped_value); + } else { + num_value = ToNumber_Inline(context(), mapped_value); } + // The only way how this can bailout is because of a detached buffer. + EmitElementStore(a(), k, num_value, source_elements_kind_, + KeyedAccessStoreMode::STANDARD_STORE, &detached, context()); + Goto(&done); - void ArrayBuiltinsAssembler::NullPostLoopAction() {} - - void ArrayBuiltinsAssembler::FillFixedArrayWithSmiZero( - TNode<FixedArray> array, TNode<Smi> smi_length) { - CSA_ASSERT(this, Word32BinaryNot(IsFixedDoubleArray(array))); + BIND(&slow); + SetPropertyStrict(context(), CAST(a()), CAST(k), CAST(mapped_value)); + Goto(&done); - TNode<IntPtrT> length = SmiToIntPtr(smi_length); - TNode<WordT> byte_length = TimesTaggedSize(length); - CSA_ASSERT(this, UintPtrLessThan(length, byte_length)); + BIND(&detached); + // tc39.github.io/ecma262/#sec-integerindexedelementset + // 8. If IsDetachedBuffer(buffer) is true, throw a TypeError exception. + ThrowTypeError(context_, MessageTemplate::kDetachedOperation, name_); - static const int32_t fa_base_data_offset = - FixedArray::kHeaderSize - kHeapObjectTag; - TNode<IntPtrT> backing_store = IntPtrAdd( - BitcastTaggedToWord(array), IntPtrConstant(fa_base_data_offset)); + BIND(&done); + return a(); +} - // Call out to memset to perform initialization. - TNode<ExternalReference> memset = - ExternalConstant(ExternalReference::libc_memset_function()); - STATIC_ASSERT(kSizetSize == kIntptrSize); - 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::NullPostLoopAction() {} + +void ArrayBuiltinsAssembler::FillFixedArrayWithSmiZero(TNode<FixedArray> array, + TNode<Smi> smi_length) { + CSA_ASSERT(this, Word32BinaryNot(IsFixedDoubleArray(array))); + + TNode<IntPtrT> length = SmiToIntPtr(smi_length); + TNode<IntPtrT> byte_length = TimesTaggedSize(length); + CSA_ASSERT(this, UintPtrLessThan(length, byte_length)); + + static const int32_t fa_base_data_offset = + FixedArray::kHeaderSize - kHeapObjectTag; + TNode<IntPtrT> backing_store = IntPtrAdd(BitcastTaggedToWord(array), + IntPtrConstant(fa_base_data_offset)); + + // Call out to memset to perform initialization. + TNode<ExternalReference> memset = + ExternalConstant(ExternalReference::libc_memset_function()); + STATIC_ASSERT(kSizetSize == kIntptrSize); + 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) { - if (argc_ == nullptr) { - Return(value); - } else { - // argc_ doesn't include the receiver, so it has to be added back in - // manually. - PopAndReturn(IntPtrAdd(argc_, IntPtrConstant(1)), value); - } +void ArrayBuiltinsAssembler::ReturnFromBuiltin(Node* value) { + if (argc_ == nullptr) { + Return(value); + } else { + // argc_ doesn't include the receiver, so it has to be added back in + // manually. + PopAndReturn(IntPtrAdd(argc_, IntPtrConstant(1)), value); } +} - void ArrayBuiltinsAssembler::InitIteratingArrayBuiltinBody( - TNode<Context> context, TNode<Object> receiver, Node* callbackfn, - Node* this_arg, TNode<IntPtrT> argc) { - context_ = context; - receiver_ = receiver; - callbackfn_ = callbackfn; - this_arg_ = this_arg; - argc_ = argc; - } +void ArrayBuiltinsAssembler::InitIteratingArrayBuiltinBody( + TNode<Context> context, TNode<Object> receiver, Node* callbackfn, + Node* this_arg, TNode<IntPtrT> argc) { + context_ = context; + receiver_ = receiver; + callbackfn_ = callbackfn; + this_arg_ = this_arg; + argc_ = argc; +} - void ArrayBuiltinsAssembler::GenerateIteratingTypedArrayBuiltinBody( - const char* name, const BuiltinResultGenerator& generator, - const CallResultProcessor& processor, const PostLoopAction& action, - ForEachDirection direction) { - name_ = name; +void ArrayBuiltinsAssembler::GenerateIteratingTypedArrayBuiltinBody( + const char* name, const BuiltinResultGenerator& generator, + const CallResultProcessor& processor, const PostLoopAction& action, + ForEachDirection direction) { + name_ = name; - // ValidateTypedArray: tc39.github.io/ecma262/#sec-validatetypedarray + // ValidateTypedArray: tc39.github.io/ecma262/#sec-validatetypedarray - Label throw_not_typed_array(this, Label::kDeferred); + Label throw_not_typed_array(this, Label::kDeferred); - GotoIf(TaggedIsSmi(receiver_), &throw_not_typed_array); - TNode<Map> typed_array_map = LoadMap(CAST(receiver_)); - GotoIfNot(IsJSTypedArrayMap(typed_array_map), &throw_not_typed_array); + GotoIf(TaggedIsSmi(receiver_), &throw_not_typed_array); + TNode<Map> typed_array_map = LoadMap(CAST(receiver_)); + GotoIfNot(IsJSTypedArrayMap(typed_array_map), &throw_not_typed_array); - TNode<JSTypedArray> typed_array = CAST(receiver_); - o_ = typed_array; + TNode<JSTypedArray> typed_array = CAST(receiver_); + o_ = typed_array; - TNode<JSArrayBuffer> array_buffer = - LoadJSArrayBufferViewBuffer(typed_array); - ThrowIfArrayBufferIsDetached(context_, array_buffer, name_); + TNode<JSArrayBuffer> array_buffer = LoadJSArrayBufferViewBuffer(typed_array); + ThrowIfArrayBufferIsDetached(context_, array_buffer, name_); - len_ = ChangeUintPtrToTagged(LoadJSTypedArrayLength(typed_array)); + len_ = ChangeUintPtrToTagged(LoadJSTypedArrayLength(typed_array)); - Label throw_not_callable(this, Label::kDeferred); - Label distinguish_types(this); - GotoIf(TaggedIsSmi(callbackfn_), &throw_not_callable); - Branch(IsCallableMap(LoadMap(callbackfn_)), &distinguish_types, - &throw_not_callable); + Label throw_not_callable(this, Label::kDeferred); + Label distinguish_types(this); + GotoIf(TaggedIsSmi(callbackfn_), &throw_not_callable); + Branch(IsCallableMap(LoadMap(callbackfn_)), &distinguish_types, + &throw_not_callable); - BIND(&throw_not_typed_array); - ThrowTypeError(context_, MessageTemplate::kNotTypedArray); + BIND(&throw_not_typed_array); + ThrowTypeError(context_, MessageTemplate::kNotTypedArray); - BIND(&throw_not_callable); - ThrowTypeError(context_, MessageTemplate::kCalledNonCallable, callbackfn_); + BIND(&throw_not_callable); + ThrowTypeError(context_, MessageTemplate::kCalledNonCallable, callbackfn_); - Label unexpected_instance_type(this); - BIND(&unexpected_instance_type); - Unreachable(); + Label unexpected_instance_type(this); + BIND(&unexpected_instance_type); + Unreachable(); - std::vector<int32_t> elements_kinds = { + std::vector<int32_t> elements_kinds = { #define ELEMENTS_KIND(Type, type, TYPE, ctype) TYPE##_ELEMENTS, - TYPED_ARRAYS(ELEMENTS_KIND) + TYPED_ARRAYS(ELEMENTS_KIND) #undef ELEMENTS_KIND - }; - std::list<Label> labels; - for (size_t i = 0; i < elements_kinds.size(); ++i) { - labels.emplace_back(this); - } - std::vector<Label*> label_ptrs; - for (Label& label : labels) { - label_ptrs.push_back(&label); - } + }; + std::list<Label> labels; + for (size_t i = 0; i < elements_kinds.size(); ++i) { + labels.emplace_back(this); + } + std::vector<Label*> label_ptrs; + for (Label& label : labels) { + label_ptrs.push_back(&label); + } - BIND(&distinguish_types); + BIND(&distinguish_types); - generator(this); + generator(this); - if (direction == ForEachDirection::kForward) { - k_.Bind(SmiConstant(0)); - } else { - k_.Bind(NumberDec(len())); - } - CSA_ASSERT(this, IsSafeInteger(k())); - TNode<Int32T> elements_kind = LoadMapElementsKind(typed_array_map); - Switch(elements_kind, &unexpected_instance_type, elements_kinds.data(), - label_ptrs.data(), labels.size()); - - size_t i = 0; - for (auto it = labels.begin(); it != labels.end(); ++i, ++it) { - BIND(&*it); - Label done(this); - source_elements_kind_ = static_cast<ElementsKind>(elements_kinds[i]); - // TODO(tebbi): Silently cancelling the loop on buffer detachment is a - // spec violation. Should go to &throw_detached and throw a TypeError - // instead. - VisitAllTypedArrayElements(array_buffer, processor, &done, direction, - typed_array); - Goto(&done); - // No exception, return success - BIND(&done); - action(this); - ReturnFromBuiltin(a_.value()); - } + if (direction == ForEachDirection::kForward) { + k_.Bind(SmiConstant(0)); + } else { + k_.Bind(NumberDec(len())); + } + CSA_ASSERT(this, IsSafeInteger(k())); + TNode<Int32T> elements_kind = LoadMapElementsKind(typed_array_map); + Switch(elements_kind, &unexpected_instance_type, elements_kinds.data(), + label_ptrs.data(), labels.size()); + + size_t i = 0; + for (auto it = labels.begin(); it != labels.end(); ++i, ++it) { + BIND(&*it); + Label done(this); + source_elements_kind_ = static_cast<ElementsKind>(elements_kinds[i]); + // TODO(tebbi): Silently cancelling the loop on buffer detachment is a + // spec violation. Should go to &throw_detached and throw a TypeError + // instead. + VisitAllTypedArrayElements(array_buffer, processor, &done, direction, + typed_array); + Goto(&done); + // No exception, return success + BIND(&done); + action(this); + ReturnFromBuiltin(a_.value()); } +} - void ArrayBuiltinsAssembler::VisitAllTypedArrayElements( - Node* array_buffer, const CallResultProcessor& processor, Label* detached, - ForEachDirection direction, TNode<JSTypedArray> typed_array) { - VariableList list({&a_, &k_, &to_}, zone()); - - FastLoopBody body = [&](Node* index) { - GotoIf(IsDetachedBuffer(CAST(array_buffer)), detached); - TNode<RawPtrT> data_ptr = LoadJSTypedArrayBackingStore(typed_array); - Node* value = LoadFixedTypedArrayElementAsTagged( - data_ptr, index, source_elements_kind_, SMI_PARAMETERS); - k_.Bind(index); - a_.Bind(processor(this, value, index)); - }; - Node* start = SmiConstant(0); - Node* end = len_; - IndexAdvanceMode advance_mode = IndexAdvanceMode::kPost; - int incr = 1; - if (direction == ForEachDirection::kReverse) { - std::swap(start, end); - advance_mode = IndexAdvanceMode::kPre; - incr = -1; - } - BuildFastLoop(list, start, end, body, incr, ParameterMode::SMI_PARAMETERS, - advance_mode); - } - - // Perform ArraySpeciesCreate (ES6 #sec-arrayspeciescreate). - void ArrayBuiltinsAssembler::GenerateArraySpeciesCreate(TNode<Number> len) { - Label runtime(this, Label::kDeferred), done(this); - - Node* const original_map = LoadMap(o()); - GotoIfNot( - InstanceTypeEqual(LoadMapInstanceType(original_map), JS_ARRAY_TYPE), - &runtime); - - GotoIfNot(IsPrototypeInitialArrayPrototype(context(), original_map), - &runtime); - - Node* species_protector = ArraySpeciesProtectorConstant(); - Node* value = - LoadObjectField(species_protector, PropertyCell::kValueOffset); - Node* const protector_invalid = SmiConstant(Isolate::kProtectorInvalid); - GotoIf(WordEqual(value, protector_invalid), &runtime); - - GotoIfNot(TaggedIsPositiveSmi(len), &runtime); - GotoIfNot( - IsValidFastJSArrayCapacity(len, CodeStubAssembler::SMI_PARAMETERS), - &runtime); - - // We need to be conservative and start with holey because the builtins - // that create output arrays aren't guaranteed to be called for every - // element in the input array (maybe the callback deletes an element). - const ElementsKind elements_kind = - GetHoleyElementsKind(GetInitialFastElementsKind()); - TNode<Context> native_context = LoadNativeContext(context()); - TNode<Map> array_map = - LoadJSArrayElementsMap(elements_kind, native_context); - a_.Bind(AllocateJSArray(PACKED_SMI_ELEMENTS, array_map, len, CAST(len), - nullptr, CodeStubAssembler::SMI_PARAMETERS, - kAllowLargeObjectAllocation)); +void ArrayBuiltinsAssembler::VisitAllTypedArrayElements( + Node* array_buffer, const CallResultProcessor& processor, Label* detached, + ForEachDirection direction, TNode<JSTypedArray> typed_array) { + VariableList list({&a_, &k_, &to_}, zone()); + + FastLoopBody body = [&](Node* index) { + GotoIf(IsDetachedBuffer(CAST(array_buffer)), detached); + TNode<RawPtrT> data_ptr = LoadJSTypedArrayBackingStore(typed_array); + auto value = LoadFixedTypedArrayElementAsTagged( + data_ptr, index, source_elements_kind_, SMI_PARAMETERS); + k_.Bind(index); + a_.Bind(processor(this, value, index)); + }; + Node* start = SmiConstant(0); + Node* end = len_; + IndexAdvanceMode advance_mode = IndexAdvanceMode::kPost; + int incr = 1; + if (direction == ForEachDirection::kReverse) { + std::swap(start, end); + advance_mode = IndexAdvanceMode::kPre; + incr = -1; + } + BuildFastLoop(list, start, end, body, incr, ParameterMode::SMI_PARAMETERS, + advance_mode); +} - Goto(&done); +// Perform ArraySpeciesCreate (ES6 #sec-arrayspeciescreate). +void ArrayBuiltinsAssembler::GenerateArraySpeciesCreate(TNode<Number> len) { + Label runtime(this, Label::kDeferred), done(this); - BIND(&runtime); - { - // 5. Let A be ? ArraySpeciesCreate(O, len). - TNode<JSReceiver> constructor = - CAST(CallRuntime(Runtime::kArraySpeciesConstructor, context(), o())); - a_.Bind(Construct(context(), constructor, len)); - Goto(&fully_spec_compliant_); - } + TNode<Map> const original_map = LoadMap(o()); + GotoIfNot(InstanceTypeEqual(LoadMapInstanceType(original_map), JS_ARRAY_TYPE), + &runtime); - BIND(&done); + GotoIfNot(IsPrototypeInitialArrayPrototype(context(), original_map), + &runtime); + + TNode<PropertyCell> species_protector = ArraySpeciesProtectorConstant(); + TNode<Object> value = + LoadObjectField(species_protector, PropertyCell::kValueOffset); + TNode<Smi> const protector_invalid = SmiConstant(Isolate::kProtectorInvalid); + GotoIf(TaggedEqual(value, protector_invalid), &runtime); + + GotoIfNot(TaggedIsPositiveSmi(len), &runtime); + GotoIfNot(IsValidFastJSArrayCapacity(len, CodeStubAssembler::SMI_PARAMETERS), + &runtime); + + // We need to be conservative and start with holey because the builtins + // that create output arrays aren't guaranteed to be called for every + // element in the input array (maybe the callback deletes an element). + const ElementsKind elements_kind = + GetHoleyElementsKind(GetInitialFastElementsKind()); + TNode<NativeContext> native_context = LoadNativeContext(context()); + TNode<Map> array_map = LoadJSArrayElementsMap(elements_kind, native_context); + a_.Bind(AllocateJSArray(PACKED_SMI_ELEMENTS, array_map, len, CAST(len), + nullptr, CodeStubAssembler::SMI_PARAMETERS, + kAllowLargeObjectAllocation)); + + Goto(&done); + + BIND(&runtime); + { + // 5. Let A be ? ArraySpeciesCreate(O, len). + TNode<JSReceiver> constructor = + CAST(CallRuntime(Runtime::kArraySpeciesConstructor, context(), o())); + a_.Bind(Construct(context(), constructor, len)); + Goto(&fully_spec_compliant_); } + BIND(&done); +} + TF_BUILTIN(ArrayPrototypePop, CodeStubAssembler) { TNode<Int32T> argc = UncheckedCast<Int32T>(Parameter(Descriptor::kJSActualArgumentsCount)); @@ -331,7 +326,7 @@ TF_BUILTIN(ArrayPrototypePop, CodeStubAssembler) { // 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)), + GotoIf(TaggedEqual(LoadMap(elements), FixedCOWArrayMapConstant()), &runtime); TNode<IntPtrT> new_length = IntPtrSub(length, IntPtrConstant(1)); @@ -353,17 +348,24 @@ TF_BUILTIN(ArrayPrototypePop, CodeStubAssembler) { Int32Constant(TERMINAL_FAST_ELEMENTS_KIND)), &fast_elements); - Node* value = LoadFixedDoubleArrayElement(CAST(elements), new_length, - &return_undefined); + { + TNode<FixedDoubleArray> elements_known_double_array = + ReinterpretCast<FixedDoubleArray>(elements); + TNode<Float64T> value = LoadFixedDoubleArrayElement( + elements_known_double_array, new_length, &return_undefined); - StoreFixedDoubleArrayHole(CAST(elements), new_length); - args.PopAndReturn(AllocateHeapNumberWithValue(value)); + StoreFixedDoubleArrayHole(elements_known_double_array, new_length); + args.PopAndReturn(AllocateHeapNumberWithValue(value)); + } BIND(&fast_elements); { - Node* value = LoadFixedArrayElement(CAST(elements), new_length); - StoreFixedArrayElement(CAST(elements), new_length, TheHoleConstant()); - GotoIf(WordEqual(value, TheHoleConstant()), &return_undefined); + TNode<FixedArray> elements_known_fixed_array = CAST(elements); + TNode<Object> value = + LoadFixedArrayElement(elements_known_fixed_array, new_length); + StoreFixedArrayElement(elements_known_fixed_array, new_length, + TheHoleConstant()); + GotoIf(TaggedEqual(value, TheHoleConstant()), &return_undefined); args.PopAndReturn(value); } @@ -415,8 +417,9 @@ TF_BUILTIN(ArrayPrototypePush, CodeStubAssembler) { GotoIf(IsElementsKindGreaterThan(kind, HOLEY_SMI_ELEMENTS), &object_push_pre); - Node* new_length = BuildAppendJSArray(PACKED_SMI_ELEMENTS, array_receiver, - &args, &arg_index, &smi_transition); + TNode<Smi> new_length = + BuildAppendJSArray(PACKED_SMI_ELEMENTS, array_receiver, &args, + &arg_index, &smi_transition); args.PopAndReturn(new_length); } @@ -426,16 +429,16 @@ TF_BUILTIN(ArrayPrototypePush, CodeStubAssembler) { // the most generic implementation for the rest of the array. BIND(&smi_transition); { - Node* arg = args.AtIndex(arg_index.value()); + TNode<Object> arg = args.AtIndex(arg_index.value()); GotoIf(TaggedIsSmi(arg), &default_label); - Node* length = LoadJSArrayLength(array_receiver); + TNode<Number> length = LoadJSArrayLength(array_receiver); // TODO(danno): Use the KeyedStoreGeneric stub here when possible, // calling into the runtime to do the elements transition is overkill. - SetPropertyStrict(context, array_receiver, CAST(length), CAST(arg)); + SetPropertyStrict(context, array_receiver, length, arg); Increment(&arg_index); // The runtime SetProperty call could have converted the array to dictionary // mode, which must be detected to abort the fast-path. - Node* kind = LoadElementsKind(array_receiver); + TNode<Int32T> kind = LoadElementsKind(array_receiver); GotoIf(Word32Equal(kind, Int32Constant(DICTIONARY_ELEMENTS)), &default_label); @@ -451,14 +454,14 @@ TF_BUILTIN(ArrayPrototypePush, CodeStubAssembler) { BIND(&object_push); { - Node* new_length = BuildAppendJSArray(PACKED_ELEMENTS, array_receiver, - &args, &arg_index, &default_label); + TNode<Smi> new_length = BuildAppendJSArray( + PACKED_ELEMENTS, array_receiver, &args, &arg_index, &default_label); args.PopAndReturn(new_length); } BIND(&double_push); { - Node* new_length = + TNode<Smi> new_length = BuildAppendJSArray(PACKED_DOUBLE_ELEMENTS, array_receiver, &args, &arg_index, &double_transition); args.PopAndReturn(new_length); @@ -470,16 +473,16 @@ TF_BUILTIN(ArrayPrototypePush, CodeStubAssembler) { // on the most generic implementation for the rest of the array. BIND(&double_transition); { - Node* arg = args.AtIndex(arg_index.value()); + TNode<Object> arg = args.AtIndex(arg_index.value()); GotoIfNumber(arg, &default_label); - Node* length = LoadJSArrayLength(array_receiver); + TNode<Number> length = LoadJSArrayLength(array_receiver); // TODO(danno): Use the KeyedStoreGeneric stub here when possible, // calling into the runtime to do the elements transition is overkill. - SetPropertyStrict(context, array_receiver, CAST(length), CAST(arg)); + SetPropertyStrict(context, array_receiver, length, arg); Increment(&arg_index); // The runtime SetProperty call could have converted the array to dictionary // mode, which must be detected to abort the fast-path. - Node* kind = LoadElementsKind(array_receiver); + TNode<Int32T> kind = LoadElementsKind(array_receiver); GotoIf(Word32Equal(kind, Int32Constant(DICTIONARY_ELEMENTS)), &default_label); Goto(&object_push); @@ -491,8 +494,8 @@ TF_BUILTIN(ArrayPrototypePush, CodeStubAssembler) { { args.ForEach( [this, array_receiver, context](Node* arg) { - Node* length = LoadJSArrayLength(array_receiver); - SetPropertyStrict(context, array_receiver, CAST(length), CAST(arg)); + TNode<Number> length = LoadJSArrayLength(array_receiver); + SetPropertyStrict(context, array_receiver, length, CAST(arg)); }, arg_index.value()); args.PopAndReturn(LoadJSArrayLength(array_receiver)); @@ -635,7 +638,7 @@ TF_BUILTIN(ArrayFrom, ArrayPopulatorAssembler) { GotoIfNot(Word32Equal(argc, Int32Constant(1)), &normal_iterate); TNode<Object> array_function = LoadContextElement( LoadNativeContext(context), Context::ARRAY_FUNCTION_INDEX); - Branch(WordEqual(array_function, receiver), &fast_iterate, &normal_iterate); + Branch(TaggedEqual(array_function, receiver), &fast_iterate, &normal_iterate); BIND(&fast_iterate); { @@ -674,7 +677,7 @@ TF_BUILTIN(ArrayFrom, ArrayPopulatorAssembler) { // Determine whether items[Symbol.iterator] is defined: IteratorBuiltinsAssembler iterator_assembler(state()); - Node* iterator_method = + TNode<Object> iterator_method = iterator_assembler.GetIteratorMethod(context, array_like); Branch(IsNullOrUndefined(iterator_method), ¬_iterable, &iterable); @@ -708,7 +711,7 @@ TF_BUILTIN(ArrayFrom, ArrayPopulatorAssembler) { IteratorRecord iterator_record = iterator_assembler.GetIterator(context, items, iterator_method); - TNode<Context> native_context = LoadNativeContext(context); + TNode<NativeContext> native_context = LoadNativeContext(context); TNode<Map> fast_iterator_result_map = CAST( LoadContextElement(native_context, Context::ITERATOR_RESULT_MAP_INDEX)); @@ -741,7 +744,7 @@ TF_BUILTIN(ArrayFrom, ArrayPopulatorAssembler) { // Store the result in the output object (catching any exceptions so the // iterator can be closed). - Node* define_status = + TNode<Object> define_status = CallRuntime(Runtime::kCreateDataProperty, context, array.value(), index.value(), value.value()); GotoIfException(define_status, &on_exception, &var_exception); @@ -789,9 +792,7 @@ TF_BUILTIN(ArrayFrom, ArrayPopulatorAssembler) { TVARIABLE(Number, index, SmiConstant(0)); - // TODO(ishell): remove <Object, Object> - GotoIf(WordEqual<Object, Object>(length.value(), SmiConstant(0)), - &finished); + GotoIf(TaggedEqual(length.value(), SmiConstant(0)), &finished); // Loop from 0 to length-1. { @@ -837,8 +838,8 @@ TF_BUILTIN(TypedArrayPrototypeMap, ArrayBuiltinsAssembler) { 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); + TNode<Object> callbackfn = args.GetOptionalArgumentValue(0); + TNode<Object> this_arg = args.GetOptionalArgumentValue(1); InitIteratingArrayBuiltinBody(context, receiver, callbackfn, this_arg, argc); @@ -856,7 +857,7 @@ TF_BUILTIN(ArrayIsArray, CodeStubAssembler) { Label call_runtime(this), return_true(this), return_false(this); GotoIf(TaggedIsSmi(object), &return_false); - TNode<Int32T> instance_type = LoadInstanceType(CAST(object)); + TNode<Uint16T> instance_type = LoadInstanceType(CAST(object)); GotoIf(InstanceTypeEqual(instance_type, JS_ARRAY_TYPE), &return_true); @@ -884,7 +885,7 @@ class ArrayIncludesIndexofAssembler : public CodeStubAssembler { void Generate(SearchVariant variant, TNode<IntPtrT> argc, TNode<Context> context); void GenerateSmiOrObject(SearchVariant variant, Node* context, Node* elements, - Node* search_element, Node* array_length, + TNode<Object> search_element, Node* array_length, Node* from_index); void GeneratePackedDoubles(SearchVariant variant, Node* elements, Node* search_element, Node* array_length, @@ -906,7 +907,7 @@ void ArrayIncludesIndexofAssembler::Generate(SearchVariant variant, TNode<Object> search_element = args.GetOptionalArgumentValue(kSearchElementArg); - Node* intptr_zero = IntPtrConstant(0); + TNode<IntPtrT> intptr_zero = IntPtrConstant(0); Label init_index(this), return_not_found(this), call_runtime(this); @@ -920,8 +921,8 @@ void ArrayIncludesIndexofAssembler::Generate(SearchVariant variant, // JSArray length is always a positive Smi for fast arrays. CSA_ASSERT(this, TaggedIsPositiveSmi(LoadJSArrayLength(array))); - Node* array_length = LoadFastJSArrayLength(array); - Node* array_length_untagged = SmiUntag(array_length); + TNode<Smi> array_length = LoadFastJSArrayLength(array); + TNode<IntPtrT> array_length_untagged = SmiUntag(array_length); { // Initialize fromIndex. @@ -930,7 +931,7 @@ void ArrayIncludesIndexofAssembler::Generate(SearchVariant variant, // If no fromIndex was passed, default to 0. GotoIf(IntPtrLessThanOrEqual(argc, IntPtrConstant(kFromIndexArg)), &done); - Node* start_from = args.AtIndex(kFromIndexArg); + TNode<Object> start_from = args.AtIndex(kFromIndexArg); // Handle Smis and undefined here and everything else in runtime. // We must be very careful with side effects from the ToInteger conversion, // as the side effects might render previously checked assumptions about @@ -944,7 +945,7 @@ void ArrayIncludesIndexofAssembler::Generate(SearchVariant variant, } BIND(&is_smi); { - Node* intptr_start_from = SmiUntag(start_from); + TNode<IntPtrT> intptr_start_from = SmiUntag(CAST(start_from)); index_var.Bind(intptr_start_from); GotoIf(IntPtrGreaterThanOrEqual(index_var.value(), intptr_zero), &done); @@ -965,7 +966,7 @@ void ArrayIncludesIndexofAssembler::Generate(SearchVariant variant, Label if_smiorobjects(this), if_packed_doubles(this), if_holey_doubles(this); TNode<Int32T> elements_kind = LoadElementsKind(array); - Node* elements = LoadElements(array); + TNode<FixedArrayBase> elements = LoadElements(array); STATIC_ASSERT(PACKED_SMI_ELEMENTS == 0); STATIC_ASSERT(HOLEY_SMI_ELEMENTS == 1); STATIC_ASSERT(PACKED_ELEMENTS == 2); @@ -977,9 +978,9 @@ void ArrayIncludesIndexofAssembler::Generate(SearchVariant variant, &if_packed_doubles); GotoIf(ElementsKindEqual(elements_kind, Int32Constant(HOLEY_DOUBLE_ELEMENTS)), &if_holey_doubles); - GotoIf( - IsElementsKindLessThanOrEqual(elements_kind, LAST_FROZEN_ELEMENTS_KIND), - &if_smiorobjects); + GotoIf(IsElementsKindLessThanOrEqual(elements_kind, + LAST_ANY_NONEXTENSIBLE_ELEMENTS_KIND), + &if_smiorobjects); Goto(&return_not_found); BIND(&if_smiorobjects); @@ -990,8 +991,8 @@ void ArrayIncludesIndexofAssembler::Generate(SearchVariant variant, Builtins::kArrayIncludesSmiOrObject) : Builtins::CallableFor(isolate(), Builtins::kArrayIndexOfSmiOrObject); - Node* result = CallStub(callable, context, elements, search_element, - array_length, SmiTag(index_var.value())); + TNode<Object> result = CallStub(callable, context, elements, search_element, + array_length, SmiTag(index_var.value())); args.PopAndReturn(result); } @@ -1003,8 +1004,8 @@ void ArrayIncludesIndexofAssembler::Generate(SearchVariant variant, Builtins::kArrayIncludesPackedDoubles) : Builtins::CallableFor(isolate(), Builtins::kArrayIndexOfPackedDoubles); - Node* result = CallStub(callable, context, elements, search_element, - array_length, SmiTag(index_var.value())); + TNode<Object> result = CallStub(callable, context, elements, search_element, + array_length, SmiTag(index_var.value())); args.PopAndReturn(result); } @@ -1016,8 +1017,8 @@ void ArrayIncludesIndexofAssembler::Generate(SearchVariant variant, Builtins::kArrayIncludesHoleyDoubles) : Builtins::CallableFor(isolate(), Builtins::kArrayIndexOfHoleyDoubles); - Node* result = CallStub(callable, context, elements, search_element, - array_length, SmiTag(index_var.value())); + TNode<Object> result = CallStub(callable, context, elements, search_element, + array_length, SmiTag(index_var.value())); args.PopAndReturn(result); } @@ -1030,7 +1031,7 @@ void ArrayIncludesIndexofAssembler::Generate(SearchVariant variant, BIND(&call_runtime); { - Node* start_from = + TNode<Object> start_from = args.GetOptionalArgumentValue(kFromIndexArg, UndefinedConstant()); Runtime::FunctionId function = variant == kIncludes ? Runtime::kArrayIncludes_Slow @@ -1041,12 +1042,11 @@ void ArrayIncludesIndexofAssembler::Generate(SearchVariant variant, } void ArrayIncludesIndexofAssembler::GenerateSmiOrObject( - SearchVariant variant, Node* context, Node* elements, Node* search_element, - Node* array_length, Node* from_index) { - VARIABLE(index_var, MachineType::PointerRepresentation(), - SmiUntag(from_index)); - VARIABLE(search_num, MachineRepresentation::kFloat64); - Node* array_length_untagged = SmiUntag(array_length); + SearchVariant variant, Node* context, Node* elements, + TNode<Object> search_element, Node* array_length, Node* from_index) { + TVARIABLE(IntPtrT, index_var, SmiUntag(from_index)); + TVARIABLE(Float64T, search_num); + TNode<IntPtrT> array_length_untagged = SmiUntag(array_length); Label ident_loop(this, &index_var), heap_num_loop(this, &search_num), string_loop(this), bigint_loop(this, &index_var), @@ -1054,20 +1054,20 @@ void ArrayIncludesIndexofAssembler::GenerateSmiOrObject( return_found(this), return_not_found(this); GotoIfNot(TaggedIsSmi(search_element), ¬_smi); - search_num.Bind(SmiToFloat64(search_element)); + search_num = SmiToFloat64(CAST(search_element)); Goto(&heap_num_loop); BIND(¬_smi); if (variant == kIncludes) { GotoIf(IsUndefined(search_element), &undef_loop); } - Node* map = LoadMap(search_element); + TNode<Map> map = LoadMap(CAST(search_element)); GotoIfNot(IsHeapNumberMap(map), ¬_heap_num); - search_num.Bind(LoadHeapNumberValue(search_element)); + search_num = LoadHeapNumberValue(CAST(search_element)); Goto(&heap_num_loop); BIND(¬_heap_num); - Node* search_type = LoadMapInstanceType(map); + TNode<Uint16T> search_type = LoadMapInstanceType(map); GotoIf(IsStringInstanceType(search_type), &string_loop); GotoIf(IsBigIntInstanceType(search_type), &bigint_loop); Goto(&ident_loop); @@ -1076,9 +1076,9 @@ void ArrayIncludesIndexofAssembler::GenerateSmiOrObject( { GotoIfNot(UintPtrLessThan(index_var.value(), array_length_untagged), &return_not_found); - Node* element_k = + TNode<Object> element_k = UnsafeLoadFixedArrayElement(CAST(elements), index_var.value()); - GotoIf(WordEqual(element_k, search_element), &return_found); + GotoIf(TaggedEqual(element_k, search_element), &return_found); Increment(&index_var); Goto(&ident_loop); @@ -1089,7 +1089,7 @@ void ArrayIncludesIndexofAssembler::GenerateSmiOrObject( GotoIfNot(UintPtrLessThan(index_var.value(), array_length_untagged), &return_not_found); - Node* element_k = + TNode<Object> element_k = UnsafeLoadFixedArrayElement(CAST(elements), index_var.value()); GotoIf(IsUndefined(element_k), &return_found); GotoIf(IsTheHole(element_k), &return_found); @@ -1109,15 +1109,16 @@ void ArrayIncludesIndexofAssembler::GenerateSmiOrObject( Label continue_loop(this), not_smi(this); GotoIfNot(UintPtrLessThan(index_var.value(), array_length_untagged), &return_not_found); - Node* element_k = + TNode<Object> element_k = UnsafeLoadFixedArrayElement(CAST(elements), index_var.value()); GotoIfNot(TaggedIsSmi(element_k), ¬_smi); - Branch(Float64Equal(search_num.value(), SmiToFloat64(element_k)), + Branch(Float64Equal(search_num.value(), SmiToFloat64(CAST(element_k))), &return_found, &continue_loop); BIND(¬_smi); - GotoIfNot(IsHeapNumber(element_k), &continue_loop); - Branch(Float64Equal(search_num.value(), LoadHeapNumberValue(element_k)), + GotoIfNot(IsHeapNumber(CAST(element_k)), &continue_loop); + Branch(Float64Equal(search_num.value(), + LoadHeapNumberValue(CAST(element_k))), &return_found, &continue_loop); BIND(&continue_loop); @@ -1131,11 +1132,11 @@ void ArrayIncludesIndexofAssembler::GenerateSmiOrObject( Label continue_loop(this); GotoIfNot(UintPtrLessThan(index_var.value(), array_length_untagged), &return_not_found); - Node* element_k = + TNode<Object> element_k = UnsafeLoadFixedArrayElement(CAST(elements), index_var.value()); GotoIf(TaggedIsSmi(element_k), &continue_loop); GotoIfNot(IsHeapNumber(CAST(element_k)), &continue_loop); - BranchIfFloat64IsNaN(LoadHeapNumberValue(element_k), &return_found, + BranchIfFloat64IsNaN(LoadHeapNumberValue(CAST(element_k)), &return_found, &continue_loop); BIND(&continue_loop); @@ -1155,24 +1156,24 @@ void ArrayIncludesIndexofAssembler::GenerateSmiOrObject( BIND(&next_iteration); GotoIfNot(UintPtrLessThan(index_var.value(), array_length_untagged), &return_not_found); - Node* element_k = + TNode<Object> element_k = UnsafeLoadFixedArrayElement(CAST(elements), index_var.value()); GotoIf(TaggedIsSmi(element_k), &continue_loop); - GotoIf(WordEqual(search_element_string, element_k), &return_found); - Node* element_k_type = LoadInstanceType(element_k); + GotoIf(TaggedEqual(search_element_string, element_k), &return_found); + TNode<Uint16T> element_k_type = LoadInstanceType(CAST(element_k)); GotoIfNot(IsStringInstanceType(element_k_type), &continue_loop); - Branch(WordEqual(search_length, LoadStringLengthAsWord(element_k)), + Branch(IntPtrEqual(search_length, LoadStringLengthAsWord(CAST(element_k))), &slow_compare, &continue_loop); BIND(&slow_compare); StringBuiltinsAssembler string_asm(state()); - string_asm.StringEqual_Core(context, search_element_string, search_type, - element_k, element_k_type, search_length, + string_asm.StringEqual_Core(search_element_string, search_type, + CAST(element_k), element_k_type, search_length, &return_found, &continue_loop, &runtime); BIND(&runtime); TNode<Object> result = CallRuntime(Runtime::kStringEqual, context, search_element_string, element_k); - Branch(WordEqual(result, TrueConstant()), &return_found, &continue_loop); + Branch(TaggedEqual(result, TrueConstant()), &return_found, &continue_loop); BIND(&continue_loop); Increment(&index_var); @@ -1184,14 +1185,14 @@ void ArrayIncludesIndexofAssembler::GenerateSmiOrObject( GotoIfNot(UintPtrLessThan(index_var.value(), array_length_untagged), &return_not_found); - Node* element_k = + TNode<Object> element_k = UnsafeLoadFixedArrayElement(CAST(elements), index_var.value()); Label continue_loop(this); GotoIf(TaggedIsSmi(element_k), &continue_loop); GotoIfNot(IsBigInt(CAST(element_k)), &continue_loop); TNode<Object> result = CallRuntime(Runtime::kBigIntEqualToBigInt, context, search_element, element_k); - Branch(WordEqual(result, TrueConstant()), &return_found, &continue_loop); + Branch(TaggedEqual(result, TrueConstant()), &return_found, &continue_loop); BIND(&continue_loop); Increment(&index_var); @@ -1217,24 +1218,23 @@ void ArrayIncludesIndexofAssembler::GeneratePackedDoubles(SearchVariant variant, Node* search_element, Node* array_length, Node* from_index) { - VARIABLE(index_var, MachineType::PointerRepresentation(), - SmiUntag(from_index)); - Node* array_length_untagged = SmiUntag(array_length); + TVARIABLE(IntPtrT, index_var, SmiUntag(from_index)); + TNode<IntPtrT> array_length_untagged = SmiUntag(array_length); Label nan_loop(this, &index_var), not_nan_loop(this, &index_var), hole_loop(this, &index_var), search_notnan(this), return_found(this), return_not_found(this); - VARIABLE(search_num, MachineRepresentation::kFloat64); - search_num.Bind(Float64Constant(0)); + TVARIABLE(Float64T, search_num); + search_num = Float64Constant(0); GotoIfNot(TaggedIsSmi(search_element), &search_notnan); - search_num.Bind(SmiToFloat64(search_element)); + search_num = SmiToFloat64(search_element); Goto(¬_nan_loop); BIND(&search_notnan); GotoIfNot(IsHeapNumber(search_element), &return_not_found); - search_num.Bind(LoadHeapNumberValue(search_element)); + search_num = LoadHeapNumberValue(search_element); Label* nan_handling = variant == kIncludes ? &nan_loop : &return_not_found; BranchIfFloat64IsNaN(search_num.value(), nan_handling, ¬_nan_loop); @@ -1244,8 +1244,8 @@ void ArrayIncludesIndexofAssembler::GeneratePackedDoubles(SearchVariant variant, Label continue_loop(this); GotoIfNot(UintPtrLessThan(index_var.value(), array_length_untagged), &return_not_found); - Node* element_k = LoadFixedDoubleArrayElement(elements, index_var.value(), - MachineType::Float64()); + TNode<Float64T> element_k = LoadFixedDoubleArrayElement( + elements, index_var.value(), MachineType::Float64()); Branch(Float64Equal(element_k, search_num.value()), &return_found, &continue_loop); BIND(&continue_loop); @@ -1259,8 +1259,8 @@ void ArrayIncludesIndexofAssembler::GeneratePackedDoubles(SearchVariant variant, Label continue_loop(this); GotoIfNot(UintPtrLessThan(index_var.value(), array_length_untagged), &return_not_found); - Node* element_k = LoadFixedDoubleArrayElement(elements, index_var.value(), - MachineType::Float64()); + TNode<Float64T> element_k = LoadFixedDoubleArrayElement( + elements, index_var.value(), MachineType::Float64()); BranchIfFloat64IsNaN(element_k, &return_found, &continue_loop); BIND(&continue_loop); Increment(&index_var); @@ -1287,18 +1287,17 @@ void ArrayIncludesIndexofAssembler::GenerateHoleyDoubles(SearchVariant variant, Node* search_element, Node* array_length, Node* from_index) { - VARIABLE(index_var, MachineType::PointerRepresentation(), - SmiUntag(from_index)); - Node* array_length_untagged = SmiUntag(array_length); + TVARIABLE(IntPtrT, index_var, SmiUntag(from_index)); + TNode<IntPtrT> array_length_untagged = SmiUntag(array_length); Label nan_loop(this, &index_var), not_nan_loop(this, &index_var), hole_loop(this, &index_var), search_notnan(this), return_found(this), return_not_found(this); - VARIABLE(search_num, MachineRepresentation::kFloat64); - search_num.Bind(Float64Constant(0)); + TVARIABLE(Float64T, search_num); + search_num = Float64Constant(0); GotoIfNot(TaggedIsSmi(search_element), &search_notnan); - search_num.Bind(SmiToFloat64(search_element)); + search_num = SmiToFloat64(search_element); Goto(¬_nan_loop); BIND(&search_notnan); @@ -1307,7 +1306,7 @@ void ArrayIncludesIndexofAssembler::GenerateHoleyDoubles(SearchVariant variant, } GotoIfNot(IsHeapNumber(search_element), &return_not_found); - search_num.Bind(LoadHeapNumberValue(search_element)); + search_num = LoadHeapNumberValue(search_element); Label* nan_handling = variant == kIncludes ? &nan_loop : &return_not_found; BranchIfFloat64IsNaN(search_num.value(), nan_handling, ¬_nan_loop); @@ -1320,8 +1319,8 @@ void ArrayIncludesIndexofAssembler::GenerateHoleyDoubles(SearchVariant variant, // No need for hole checking here; the following Float64Equal will // return 'not equal' for holes anyway. - Node* element_k = LoadFixedDoubleArrayElement(elements, index_var.value(), - MachineType::Float64()); + TNode<Float64T> element_k = LoadFixedDoubleArrayElement( + elements, index_var.value(), MachineType::Float64()); Branch(Float64Equal(element_k, search_num.value()), &return_found, &continue_loop); @@ -1338,7 +1337,7 @@ void ArrayIncludesIndexofAssembler::GenerateHoleyDoubles(SearchVariant variant, &return_not_found); // Load double value or continue if it's the hole NaN. - Node* element_k = LoadFixedDoubleArrayElement( + TNode<Float64T> element_k = LoadFixedDoubleArrayElement( elements, index_var.value(), MachineType::Float64(), 0, INTPTR_PARAMETERS, &continue_loop); @@ -1387,9 +1386,9 @@ TF_BUILTIN(ArrayIncludes, ArrayIncludesIndexofAssembler) { } TF_BUILTIN(ArrayIncludesSmiOrObject, ArrayIncludesIndexofAssembler) { - Node* context = Parameter(Descriptor::kContext); + TNode<Context> context = CAST(Parameter(Descriptor::kContext)); Node* elements = Parameter(Descriptor::kElements); - Node* search_element = Parameter(Descriptor::kSearchElement); + TNode<Object> search_element = CAST(Parameter(Descriptor::kSearchElement)); Node* array_length = Parameter(Descriptor::kLength); Node* from_index = Parameter(Descriptor::kFromIndex); @@ -1426,9 +1425,9 @@ TF_BUILTIN(ArrayIndexOf, ArrayIncludesIndexofAssembler) { } TF_BUILTIN(ArrayIndexOfSmiOrObject, ArrayIncludesIndexofAssembler) { - Node* context = Parameter(Descriptor::kContext); + TNode<Context> context = CAST(Parameter(Descriptor::kContext)); Node* elements = Parameter(Descriptor::kElements); - Node* search_element = Parameter(Descriptor::kSearchElement); + TNode<Object> search_element = CAST(Parameter(Descriptor::kSearchElement)); Node* array_length = Parameter(Descriptor::kLength); Node* from_index = Parameter(Descriptor::kFromIndex); @@ -1512,7 +1511,7 @@ TF_BUILTIN(ArrayIteratorPrototypeNext, CodeStubAssembler) { // Dispatch based on the type of the {array}. TNode<Map> array_map = LoadMap(array); - TNode<Int32T> array_type = LoadMapInstanceType(array_map); + TNode<Uint16T> array_type = LoadMapInstanceType(array_map); GotoIf(InstanceTypeEqual(array_type, JS_ARRAY_TYPE), &if_array); Branch(InstanceTypeEqual(array_type, JS_TYPED_ARRAY_TYPE), &if_typedarray, &if_other); @@ -1662,7 +1661,7 @@ TF_BUILTIN(ArrayIteratorPrototypeNext, CodeStubAssembler) { BIND(&allocate_iterator_result); { - Node* result = + TNode<JSObject> result = AllocateJSIteratorResult(context, var_value.value(), var_done.value()); Return(result); } @@ -1705,7 +1704,7 @@ class ArrayFlattenAssembler : public CodeStubAssembler { // b. Let exists be ? HasProperty(source, P). CSA_ASSERT(this, SmiGreaterThanOrEqual(CAST(source_index), SmiConstant(0))); - Node* const exists = + TNode<Oddball> const exists = HasProperty(context, source, source_index, kHasProperty); // c. If exists is true, then @@ -1713,7 +1712,8 @@ class ArrayFlattenAssembler : public CodeStubAssembler { GotoIfNot(IsTrue(exists), &next); { // i. Let element be ? Get(source, P). - Node* element = GetProperty(context, source, source_index); + TNode<Object> element_maybe_smi = + GetProperty(context, source, source_index); // ii. If mapperFunction is present, then if (mapper_function != nullptr) { @@ -1723,9 +1723,9 @@ class ArrayFlattenAssembler : public CodeStubAssembler { // 1. Set element to ? Call(mapperFunction, thisArg , « element, // sourceIndex, source »). - element = + element_maybe_smi = CAST( CallJS(CodeFactory::Call(isolate()), context, mapper_function, - this_arg, element, source_index, source); + this_arg, element_maybe_smi, source_index, source)); } // iii. Let shouldFlatten be false. @@ -1734,7 +1734,8 @@ class ArrayFlattenAssembler : public CodeStubAssembler { // iv. If depth > 0, then GotoIfNumberGreaterThanOrEqual(SmiConstant(0), depth, &if_noflatten); // 1. Set shouldFlatten to ? IsArray(element). - GotoIf(TaggedIsSmi(element), &if_noflatten); + GotoIf(TaggedIsSmi(element_maybe_smi), &if_noflatten); + TNode<HeapObject> element = CAST(element_maybe_smi); GotoIf(IsJSArray(element), &if_flatten_array); GotoIfNot(IsJSProxy(element), &if_noflatten); Branch(IsTrue(CallRuntime(Runtime::kArrayIsArray, context, element)), @@ -1745,7 +1746,7 @@ class ArrayFlattenAssembler : public CodeStubAssembler { CSA_ASSERT(this, IsJSArray(element)); // 1. Let elementLen be ? ToLength(? Get(element, "length")). - Node* const element_length = + TNode<Object> const element_length = LoadObjectField(element, JSArray::kLengthOffset); // 2. Set targetIndex to ? FlattenIntoArray(target, element, @@ -1762,7 +1763,7 @@ class ArrayFlattenAssembler : public CodeStubAssembler { CSA_ASSERT(this, IsJSProxy(element)); // 1. Let elementLen be ? ToLength(? Get(element, "length")). - Node* const element_length = ToLength_Inline( + TNode<Number> const element_length = ToLength_Inline( context, GetProperty(context, element, LengthStringConstant())); // 2. Set targetIndex to ? FlattenIntoArray(target, element, @@ -1872,7 +1873,7 @@ TF_BUILTIN(ArrayPrototypeFlat, CodeStubAssembler) { // 5. Let A be ? ArraySpeciesCreate(O, 0). TNode<JSReceiver> const constructor = CAST(CallRuntime(Runtime::kArraySpeciesConstructor, context, o)); - Node* const a = Construct(context, constructor, SmiConstant(0)); + TNode<JSReceiver> const a = Construct(context, constructor, SmiConstant(0)); // 6. Perform ? FlattenIntoArray(A, O, sourceLen, 0, depthNum). CallBuiltin(Builtins::kFlattenIntoArray, context, a, o, source_length, @@ -1937,7 +1938,7 @@ TF_BUILTIN(ArrayConstructor, ArrayBuiltinsAssembler) { SelectConstant<Object>(IsUndefined(new_target), function, new_target); // Run the native code for the Array function called as a normal function. - TNode<Object> no_allocation_site = UndefinedConstant(); + TNode<Oddball> no_allocation_site = UndefinedConstant(); TailCallBuiltin(Builtins::kArrayConstructorImpl, context, function, new_target, argc, no_allocation_site); } @@ -2105,7 +2106,7 @@ TF_BUILTIN(ArrayConstructorImpl, ArrayBuiltinsAssembler) { CAST(LoadObjectField(target, JSFunction::kContextOffset)); Label runtime(this, Label::kDeferred); - GotoIf(WordNotEqual(target, new_target), &runtime); + GotoIf(TaggedNotEqual(target, new_target), &runtime); Label no_info(this); // If the feedback vector is the undefined value call an array constructor @@ -2143,7 +2144,8 @@ void ArrayBuiltinsAssembler::GenerateConstructor( Branch(SmiEqual(CAST(array_size), SmiConstant(0)), &small_smi_size, &abort); BIND(&abort); - Node* reason = SmiConstant(AbortReason::kAllocatingNonEmptyPackedArray); + TNode<Smi> reason = + SmiConstant(AbortReason::kAllocatingNonEmptyPackedArray); TailCallRuntime(Runtime::kAbort, context, reason); } else { int element_size = @@ -2175,8 +2177,8 @@ void ArrayBuiltinsAssembler::GenerateConstructor( void ArrayBuiltinsAssembler::GenerateArrayNoArgumentConstructor( ElementsKind kind, AllocationSiteOverrideMode mode) { using Descriptor = ArrayNoArgumentConstructorDescriptor; - Node* native_context = LoadObjectField(Parameter(Descriptor::kFunction), - JSFunction::kContextOffset); + TNode<NativeContext> native_context = CAST(LoadObjectField( + Parameter(Descriptor::kFunction), JSFunction::kContextOffset)); bool track_allocation_site = AllocationSite::ShouldTrack(kind) && mode != DISABLE_ALLOCATION_SITES; Node* allocation_site = @@ -2191,10 +2193,11 @@ void ArrayBuiltinsAssembler::GenerateArrayNoArgumentConstructor( void ArrayBuiltinsAssembler::GenerateArraySingleArgumentConstructor( ElementsKind kind, AllocationSiteOverrideMode mode) { using Descriptor = ArraySingleArgumentConstructorDescriptor; - Node* context = Parameter(Descriptor::kContext); + TNode<Context> context = CAST(Parameter(Descriptor::kContext)); Node* function = Parameter(Descriptor::kFunction); - Node* native_context = LoadObjectField(function, JSFunction::kContextOffset); - Node* array_map = LoadJSArrayElementsMap(kind, native_context); + TNode<NativeContext> native_context = + CAST(LoadObjectField(function, JSFunction::kContextOffset)); + TNode<Map> array_map = LoadJSArrayElementsMap(kind, native_context); AllocationSiteMode allocation_site_mode = DONT_TRACK_ALLOCATION_SITE; if (mode == DONT_OVERRIDE) { diff --git a/deps/v8/src/builtins/builtins-array.cc b/deps/v8/src/builtins/builtins-array.cc index 96c10ed0fd..6c3e724649 100644 --- a/deps/v8/src/builtins/builtins-array.cc +++ b/deps/v8/src/builtins/builtins-array.cc @@ -7,6 +7,7 @@ #include "src/codegen/code-factory.h" #include "src/debug/debug.h" #include "src/execution/isolate.h" +#include "src/execution/protectors-inl.h" #include "src/handles/global-handles.h" #include "src/logging/counters.h" #include "src/objects/contexts.h" @@ -782,10 +783,10 @@ class ArrayConcatVisitor { storage_ = isolate_->global_handles()->Create(storage); } - class FastElementsField : public BitField<bool, 0, 1> {}; - class ExceedsLimitField : public BitField<bool, 1, 1> {}; - class IsFixedArrayField : public BitField<bool, 2, 1> {}; - class HasSimpleElementsField : public BitField<bool, 3, 1> {}; + using FastElementsField = BitField<bool, 0, 1>; + using ExceedsLimitField = BitField<bool, 1, 1>; + using IsFixedArrayField = BitField<bool, 2, 1>; + using HasSimpleElementsField = BitField<bool, 3, 1>; bool fast_elements() const { return FastElementsField::decode(bit_field_); } void set_fast_elements(bool fast) { @@ -819,8 +820,10 @@ uint32_t EstimateElementCount(Isolate* isolate, Handle<JSArray> array) { case PACKED_ELEMENTS: case PACKED_FROZEN_ELEMENTS: case PACKED_SEALED_ELEMENTS: + case PACKED_NONEXTENSIBLE_ELEMENTS: case HOLEY_FROZEN_ELEMENTS: case HOLEY_SEALED_ELEMENTS: + case HOLEY_NONEXTENSIBLE_ELEMENTS: case HOLEY_ELEMENTS: { // Fast elements can't have lengths that are not representable by // a 32-bit signed integer. @@ -887,9 +890,11 @@ void CollectElementIndices(Isolate* isolate, Handle<JSObject> object, case PACKED_ELEMENTS: case PACKED_FROZEN_ELEMENTS: case PACKED_SEALED_ELEMENTS: + case PACKED_NONEXTENSIBLE_ELEMENTS: case HOLEY_SMI_ELEMENTS: case HOLEY_FROZEN_ELEMENTS: case HOLEY_SEALED_ELEMENTS: + case HOLEY_NONEXTENSIBLE_ELEMENTS: case HOLEY_ELEMENTS: { DisallowHeapAllocation no_gc; FixedArray elements = FixedArray::cast(object->elements()); @@ -1063,9 +1068,11 @@ bool IterateElements(Isolate* isolate, Handle<JSReceiver> receiver, case PACKED_ELEMENTS: case PACKED_FROZEN_ELEMENTS: case PACKED_SEALED_ELEMENTS: + case PACKED_NONEXTENSIBLE_ELEMENTS: case HOLEY_SMI_ELEMENTS: case HOLEY_FROZEN_ELEMENTS: case HOLEY_SEALED_ELEMENTS: + case HOLEY_NONEXTENSIBLE_ELEMENTS: case HOLEY_ELEMENTS: { // Run through the elements FixedArray and use HasElement and GetElement // to check the prototype for missing elements. @@ -1219,7 +1226,7 @@ Object Slow_ArrayConcat(BuiltinArguments* args, Handle<Object> species, if (length_estimate != 0) { ElementsKind array_kind = GetPackedElementsKind(array->GetElementsKind()); - if (IsFrozenOrSealedElementsKind(array_kind)) { + if (IsAnyNonextensibleElementsKind(array_kind)) { array_kind = PACKED_ELEMENTS; } kind = GetMoreGeneralElementsKind(kind, array_kind); @@ -1315,9 +1322,11 @@ Object Slow_ArrayConcat(BuiltinArguments* args, Handle<Object> species, case HOLEY_ELEMENTS: case HOLEY_FROZEN_ELEMENTS: case HOLEY_SEALED_ELEMENTS: + case HOLEY_NONEXTENSIBLE_ELEMENTS: case PACKED_ELEMENTS: case PACKED_FROZEN_ELEMENTS: case PACKED_SEALED_ELEMENTS: + case PACKED_NONEXTENSIBLE_ELEMENTS: case DICTIONARY_ELEMENTS: case NO_ELEMENTS: DCHECK_EQ(0u, length); @@ -1460,7 +1469,7 @@ BUILTIN(ArrayConcat) { // Avoid a real species read to avoid extra lookups to the array constructor if (V8_LIKELY(receiver->IsJSArray() && Handle<JSArray>::cast(receiver)->HasArrayPrototype(isolate) && - isolate->IsArraySpeciesLookupChainIntact())) { + Protectors::IsArraySpeciesLookupChainIntact(isolate))) { if (Fast_ArrayConcat(isolate, &args).ToHandle(&result_array)) { return *result_array; } diff --git a/deps/v8/src/builtins/builtins-async-function-gen.cc b/deps/v8/src/builtins/builtins-async-function-gen.cc index a95365e425..6ac37da3f6 100644 --- a/deps/v8/src/builtins/builtins-async-function-gen.cc +++ b/deps/v8/src/builtins/builtins-async-function-gen.cc @@ -109,7 +109,7 @@ TF_BUILTIN(AsyncFunctionEnter, AsyncFunctionBuiltinsAssembler) { TNode<HeapObject> base = AllocateInNewSpace(size); // Initialize the promise. - TNode<Context> native_context = LoadNativeContext(context); + TNode<NativeContext> native_context = LoadNativeContext(context); TNode<JSFunction> promise_function = CAST(LoadContextElement(native_context, Context::PROMISE_FUNCTION_INDEX)); TNode<Map> promise_map = LoadObjectField<Map>( @@ -263,8 +263,8 @@ void AsyncFunctionBuiltinsAssembler::AsyncFunctionAwait( TNode<Object> value = CAST(Parameter(Descriptor::kValue)); TNode<Context> context = CAST(Parameter(Descriptor::kContext)); - Node* outer_promise = LoadObjectField(async_function_object, - JSAsyncFunctionObject::kPromiseOffset); + TNode<Object> outer_promise = LoadObjectField( + async_function_object, JSAsyncFunctionObject::kPromiseOffset); Label after_debug_hook(this), call_debug_hook(this, Label::kDeferred); GotoIf(HasAsyncEventDelegate(), &call_debug_hook); diff --git a/deps/v8/src/builtins/builtins-async-gen.cc b/deps/v8/src/builtins/builtins-async-gen.cc index 6c04037a63..70d4eac9c8 100644 --- a/deps/v8/src/builtins/builtins-async-gen.cc +++ b/deps/v8/src/builtins/builtins-async-gen.cc @@ -28,7 +28,7 @@ Node* AsyncBuiltinsAssembler::AwaitOld(Node* context, Node* generator, Node* on_resolve_context_index, Node* on_reject_context_index, Node* is_predicted_as_caught) { - Node* const native_context = LoadNativeContext(context); + TNode<NativeContext> const native_context = LoadNativeContext(context); static const int kWrappedPromiseOffset = FixedArray::SizeFor(Context::MIN_CONTEXT_SLOTS); @@ -46,7 +46,7 @@ Node* AsyncBuiltinsAssembler::AwaitOld(Node* context, Node* generator, StoreMapNoWriteBarrier(closure_context, RootIndex::kAwaitContextMap); StoreObjectFieldNoWriteBarrier(closure_context, Context::kLengthOffset, SmiConstant(Context::MIN_CONTEXT_SLOTS)); - Node* const empty_scope_info = + TNode<Object> const empty_scope_info = LoadContextElement(native_context, Context::SCOPE_INFO_INDEX); StoreContextElementNoWriteBarrier( closure_context, Context::SCOPE_INFO_INDEX, empty_scope_info); @@ -59,16 +59,17 @@ Node* AsyncBuiltinsAssembler::AwaitOld(Node* context, Node* generator, } // Let promiseCapability be ! NewPromiseCapability(%Promise%). - Node* const promise_fun = - LoadContextElement(native_context, Context::PROMISE_FUNCTION_INDEX); + TNode<JSFunction> const promise_fun = + CAST(LoadContextElement(native_context, Context::PROMISE_FUNCTION_INDEX)); CSA_ASSERT(this, IsFunctionWithPrototypeSlotMap(LoadMap(promise_fun))); - Node* const promise_map = - LoadObjectField(promise_fun, JSFunction::kPrototypeOrInitialMapOffset); + TNode<Map> const promise_map = CAST( + LoadObjectField(promise_fun, JSFunction::kPrototypeOrInitialMapOffset)); // Assert that the JSPromise map has an instance size is // JSPromise::kSizeWithEmbedderFields. - CSA_ASSERT(this, WordEqual(LoadMapInstanceSizeInWords(promise_map), - IntPtrConstant(JSPromise::kSizeWithEmbedderFields / - kTaggedSize))); + CSA_ASSERT(this, + IntPtrEqual(LoadMapInstanceSizeInWords(promise_map), + IntPtrConstant(JSPromise::kSizeWithEmbedderFields / + kTaggedSize))); TNode<HeapObject> wrapped_value = InnerAllocate(base, kWrappedPromiseOffset); { // Initialize Promise @@ -118,7 +119,7 @@ Node* AsyncBuiltinsAssembler::AwaitOptimized(Node* context, Node* generator, Node* on_resolve_context_index, Node* on_reject_context_index, Node* is_predicted_as_caught) { - Node* const native_context = LoadNativeContext(context); + TNode<NativeContext> const native_context = LoadNativeContext(context); CSA_ASSERT(this, IsJSPromise(promise)); static const int kResolveClosureOffset = @@ -139,7 +140,7 @@ Node* AsyncBuiltinsAssembler::AwaitOptimized(Node* context, Node* generator, StoreMapNoWriteBarrier(closure_context, RootIndex::kAwaitContextMap); StoreObjectFieldNoWriteBarrier(closure_context, Context::kLengthOffset, SmiConstant(Context::MIN_CONTEXT_SLOTS)); - Node* const empty_scope_info = + TNode<Object> const empty_scope_info = LoadContextElement(native_context, Context::SCOPE_INFO_INDEX); StoreContextElementNoWriteBarrier( closure_context, Context::SCOPE_INFO_INDEX, empty_scope_info); @@ -196,16 +197,16 @@ Node* AsyncBuiltinsAssembler::Await(Node* context, Node* generator, Node* value, // to allocate the wrapper promise and can just use the `AwaitOptimized` // logic. GotoIf(TaggedIsSmi(value), &if_old); - Node* const value_map = LoadMap(value); + TNode<Map> const value_map = LoadMap(value); GotoIfNot(IsJSPromiseMap(value_map), &if_old); // We can skip the "constructor" lookup on {value} if it's [[Prototype]] // is the (initial) Promise.prototype and the @@species protector is // intact, as that guards the lookup path for "constructor" on // JSPromise instances which have the (initial) Promise.prototype. - Node* const native_context = LoadNativeContext(context); - Node* const promise_prototype = + TNode<NativeContext> const native_context = LoadNativeContext(context); + TNode<Object> const promise_prototype = LoadContextElement(native_context, Context::PROMISE_PROTOTYPE_INDEX); - GotoIfNot(WordEqual(LoadMapPrototype(value_map), promise_prototype), + GotoIfNot(TaggedEqual(LoadMapPrototype(value_map), promise_prototype), &if_slow_constructor); Branch(IsPromiseSpeciesProtectorCellInvalid(), &if_slow_constructor, &if_new); @@ -214,11 +215,11 @@ Node* AsyncBuiltinsAssembler::Await(Node* context, Node* generator, Node* value, // have the %Promise% as its "constructor", so we need to check that as well. BIND(&if_slow_constructor); { - Node* const value_constructor = + TNode<Object> const value_constructor = GetProperty(context, value, isolate()->factory()->constructor_string()); - Node* const promise_function = + TNode<Object> const promise_function = LoadContextElement(native_context, Context::PROMISE_FUNCTION_INDEX); - Branch(WordEqual(value_constructor, promise_function), &if_new, &if_old); + Branch(TaggedEqual(value_constructor, promise_function), &if_new, &if_old); } BIND(&if_old); @@ -245,9 +246,10 @@ void AsyncBuiltinsAssembler::InitializeNativeClosure(Node* context, native_context, Context::STRICT_FUNCTION_WITHOUT_PROTOTYPE_MAP_INDEX)); // Ensure that we don't have to initialize prototype_or_initial_map field of // JSFunction. - CSA_ASSERT(this, WordEqual(LoadMapInstanceSizeInWords(function_map), - IntPtrConstant(JSFunction::kSizeWithoutPrototype / - kTaggedSize))); + CSA_ASSERT(this, + IntPtrEqual(LoadMapInstanceSizeInWords(function_map), + IntPtrConstant(JSFunction::kSizeWithoutPrototype / + kTaggedSize))); STATIC_ASSERT(JSFunction::kSizeWithoutPrototype == 7 * kTaggedSize); StoreMapNoWriteBarrier(function, function_map); StoreObjectFieldRoot(function, JSObject::kPropertiesOrHashOffset, @@ -276,12 +278,10 @@ void AsyncBuiltinsAssembler::InitializeNativeClosure(Node* context, Node* AsyncBuiltinsAssembler::CreateUnwrapClosure(Node* native_context, Node* done) { - Node* const map = LoadContextElement( + TNode<Object> const map = LoadContextElement( native_context, Context::STRICT_FUNCTION_WITHOUT_PROTOTYPE_MAP_INDEX); - Node* const on_fulfilled_shared = LoadContextElement( - native_context, Context::ASYNC_ITERATOR_VALUE_UNWRAP_SHARED_FUN); - CSA_ASSERT(this, - HasInstanceType(on_fulfilled_shared, SHARED_FUNCTION_INFO_TYPE)); + TNode<SharedFunctionInfo> const on_fulfilled_shared = CAST(LoadContextElement( + native_context, Context::ASYNC_ITERATOR_VALUE_UNWRAP_SHARED_FUN)); Node* const closure_context = AllocateAsyncIteratorValueUnwrapContext(native_context, done); return AllocateFunctionWithMapAndContext(map, on_fulfilled_shared, @@ -304,10 +304,11 @@ TF_BUILTIN(AsyncIteratorValueUnwrap, AsyncBuiltinsAssembler) { Node* const value = Parameter(Descriptor::kValue); Node* const context = Parameter(Descriptor::kContext); - Node* const done = LoadContextElement(context, ValueUnwrapContext::kDoneSlot); - CSA_ASSERT(this, IsBoolean(done)); + TNode<Object> const done = + LoadContextElement(context, ValueUnwrapContext::kDoneSlot); + CSA_ASSERT(this, IsBoolean(CAST(done))); - Node* const unwrapped_value = + TNode<Object> const unwrapped_value = CallBuiltin(Builtins::kCreateIterResultObject, context, value, done); Return(unwrapped_value); diff --git a/deps/v8/src/builtins/builtins-async-generator-gen.cc b/deps/v8/src/builtins/builtins-async-generator-gen.cc index d14e811db8..8053cf0dc8 100644 --- a/deps/v8/src/builtins/builtins-async-generator-gen.cc +++ b/deps/v8/src/builtins/builtins-async-generator-gen.cc @@ -25,12 +25,12 @@ class AsyncGeneratorBuiltinsAssembler : public AsyncBuiltinsAssembler { inline Node* TaggedIsAsyncGenerator(Node* tagged_object) { TNode<BoolT> if_notsmi = TaggedIsNotSmi(tagged_object); - return Select<BoolT>(if_notsmi, - [=] { - return HasInstanceType( - tagged_object, JS_ASYNC_GENERATOR_OBJECT_TYPE); - }, - [=] { return if_notsmi; }); + return Select<BoolT>( + if_notsmi, + [=] { + return HasInstanceType(tagged_object, JS_ASYNC_GENERATOR_OBJECT_TYPE); + }, + [=] { return if_notsmi; }); } inline Node* LoadGeneratorState(Node* const generator) { return LoadObjectField(generator, JSGeneratorObject::kContinuationOffset); @@ -68,7 +68,7 @@ class AsyncGeneratorBuiltinsAssembler : public AsyncBuiltinsAssembler { inline TNode<BoolT> IsGeneratorAwaiting(Node* const generator) { TNode<Object> is_generator_awaiting = LoadObjectField(generator, JSAsyncGeneratorObject::kIsAwaitingOffset); - return WordEqual(is_generator_awaiting, SmiConstant(1)); + return TaggedEqual(is_generator_awaiting, SmiConstant(1)); } inline void SetGeneratorAwaiting(Node* const generator) { @@ -93,8 +93,8 @@ class AsyncGeneratorBuiltinsAssembler : public AsyncBuiltinsAssembler { inline Node* IsFastJSIterResult(Node* const value, Node* const context) { CSA_ASSERT(this, TaggedIsNotSmi(value)); - Node* const native_context = LoadNativeContext(context); - return WordEqual( + TNode<NativeContext> const native_context = LoadNativeContext(context); + return TaggedEqual( LoadMap(value), LoadContextElement(native_context, Context::ITERATOR_RESULT_MAP_INDEX)); } @@ -200,7 +200,7 @@ Node* AsyncGeneratorBuiltinsAssembler::AllocateAsyncGeneratorRequest( JSAsyncGeneratorObject::ResumeMode resume_mode, Node* resume_value, Node* promise) { CSA_SLOW_ASSERT(this, HasInstanceType(promise, JS_PROMISE_TYPE)); - Node* request = Allocate(AsyncGeneratorRequest::kSize); + TNode<HeapObject> request = Allocate(AsyncGeneratorRequest::kSize); StoreMapNoWriteBarrier(request, RootIndex::kAsyncGeneratorRequestMap); StoreObjectFieldNoWriteBarrier(request, AsyncGeneratorRequest::kNextOffset, UndefinedConstant()); @@ -219,7 +219,8 @@ Node* AsyncGeneratorBuiltinsAssembler::AllocateAsyncGeneratorRequest( void AsyncGeneratorBuiltinsAssembler::AsyncGeneratorAwaitResumeClosure( Node* context, Node* value, JSAsyncGeneratorObject::ResumeMode resume_mode) { - Node* const generator = LoadContextElement(context, Context::EXTENSION_INDEX); + TNode<Object> const generator = + LoadContextElement(context, Context::EXTENSION_INDEX); CSA_SLOW_ASSERT(this, TaggedIsAsyncGenerator(generator)); SetGeneratorNotAwaiting(generator); @@ -276,7 +277,8 @@ void AsyncGeneratorBuiltinsAssembler::AddAsyncGeneratorRequestToQueue( { Label loop_next(this), next_empty(this); Node* current = var_current.value(); - Node* next = LoadObjectField(current, AsyncGeneratorRequest::kNextOffset); + TNode<Object> next = + LoadObjectField(current, AsyncGeneratorRequest::kNextOffset); Branch(IsUndefined(next), &next_empty, &loop_next); BIND(&next_empty); @@ -299,11 +301,11 @@ Node* AsyncGeneratorBuiltinsAssembler::TakeFirstAsyncGeneratorRequestFromQueue( // Removes and returns the first AsyncGeneratorRequest from a // JSAsyncGeneratorObject's queue. Asserts that the queue is not empty. CSA_ASSERT(this, TaggedIsAsyncGenerator(generator)); - Node* request = - LoadObjectField(generator, JSAsyncGeneratorObject::kQueueOffset); - CSA_ASSERT(this, IsNotUndefined(request)); + TNode<AsyncGeneratorRequest> request = + CAST(LoadObjectField(generator, JSAsyncGeneratorObject::kQueueOffset)); - Node* next = LoadObjectField(request, AsyncGeneratorRequest::kNextOffset); + TNode<Object> next = + LoadObjectField(request, AsyncGeneratorRequest::kNextOffset); StoreObjectField(generator, JSAsyncGeneratorObject::kQueueOffset, next); return request; @@ -315,12 +317,12 @@ Node* AsyncGeneratorBuiltinsAssembler::TakeFirstAsyncGeneratorRequestFromQueue( TF_BUILTIN(AsyncGeneratorPrototypeNext, AsyncGeneratorBuiltinsAssembler) { const int kValueArg = 0; - Node* argc = + TNode<IntPtrT> argc = ChangeInt32ToIntPtr(Parameter(Descriptor::kJSActualArgumentsCount)); CodeStubArguments args(this, argc); - Node* generator = args.GetReceiver(); - Node* value = args.GetOptionalArgumentValue(kValueArg); + TNode<Object> generator = args.GetReceiver(); + TNode<Object> value = args.GetOptionalArgumentValue(kValueArg); Node* context = Parameter(Descriptor::kContext); AsyncGeneratorEnqueue(&args, context, generator, value, @@ -333,12 +335,12 @@ TF_BUILTIN(AsyncGeneratorPrototypeNext, AsyncGeneratorBuiltinsAssembler) { TF_BUILTIN(AsyncGeneratorPrototypeReturn, AsyncGeneratorBuiltinsAssembler) { const int kValueArg = 0; - Node* argc = + TNode<IntPtrT> argc = ChangeInt32ToIntPtr(Parameter(Descriptor::kJSActualArgumentsCount)); CodeStubArguments args(this, argc); - Node* generator = args.GetReceiver(); - Node* value = args.GetOptionalArgumentValue(kValueArg); + TNode<Object> generator = args.GetReceiver(); + TNode<Object> value = args.GetOptionalArgumentValue(kValueArg); Node* context = Parameter(Descriptor::kContext); AsyncGeneratorEnqueue(&args, context, generator, value, @@ -351,12 +353,12 @@ TF_BUILTIN(AsyncGeneratorPrototypeReturn, AsyncGeneratorBuiltinsAssembler) { TF_BUILTIN(AsyncGeneratorPrototypeThrow, AsyncGeneratorBuiltinsAssembler) { const int kValueArg = 0; - Node* argc = + TNode<IntPtrT> argc = ChangeInt32ToIntPtr(Parameter(Descriptor::kJSActualArgumentsCount)); CodeStubArguments args(this, argc); - Node* generator = args.GetReceiver(); - Node* value = args.GetOptionalArgumentValue(kValueArg); + TNode<Object> generator = args.GetReceiver(); + TNode<Object> value = args.GetOptionalArgumentValue(kValueArg); Node* context = Parameter(Descriptor::kContext); AsyncGeneratorEnqueue(&args, context, generator, value, @@ -446,8 +448,8 @@ TF_BUILTIN(AsyncGeneratorResumeNext, AsyncGeneratorBuiltinsAssembler) { // generator is not closed, resume the generator with a "throw" completion. // If the generator was closed, perform AsyncGeneratorReject(thrownValue). // In all cases, the last step is to call AsyncGeneratorResumeNext. - Node* is_caught = CallRuntime(Runtime::kAsyncGeneratorHasCatchHandlerForPC, - context, generator); + TNode<Object> is_caught = CallRuntime( + Runtime::kAsyncGeneratorHasCatchHandlerForPC, context, generator); TailCallBuiltin(Builtins::kAsyncGeneratorReturn, context, generator, next_value, is_caught); @@ -501,10 +503,10 @@ TF_BUILTIN(AsyncGeneratorResolve, AsyncGeneratorBuiltinsAssembler) { Node* const promise = LoadPromiseFromAsyncGeneratorRequest(next); // Let iteratorResult be CreateIterResultObject(value, done). - Node* const iter_result = Allocate(JSIteratorResult::kSize); + TNode<HeapObject> const iter_result = Allocate(JSIteratorResult::kSize); { - Node* map = LoadContextElement(LoadNativeContext(context), - Context::ITERATOR_RESULT_MAP_INDEX); + TNode<Object> map = LoadContextElement(LoadNativeContext(context), + Context::ITERATOR_RESULT_MAP_INDEX); StoreMapNoWriteBarrier(iter_result, map); StoreObjectFieldRoot(iter_result, JSIteratorResult::kPropertiesOrHashOffset, RootIndex::kEmptyFixedArray); @@ -585,7 +587,8 @@ TF_BUILTIN(AsyncGeneratorYield, AsyncGeneratorBuiltinsAssembler) { TF_BUILTIN(AsyncGeneratorYieldResolveClosure, AsyncGeneratorBuiltinsAssembler) { Node* const context = Parameter(Descriptor::kContext); Node* const value = Parameter(Descriptor::kValue); - Node* const generator = LoadContextElement(context, Context::EXTENSION_INDEX); + TNode<Object> const generator = + LoadContextElement(context, Context::EXTENSION_INDEX); SetGeneratorNotAwaiting(generator); @@ -665,7 +668,8 @@ TF_BUILTIN(AsyncGeneratorReturnClosedResolveClosure, AsyncGeneratorBuiltinsAssembler) { Node* const context = Parameter(Descriptor::kContext); Node* const value = Parameter(Descriptor::kValue); - Node* const generator = LoadContextElement(context, Context::EXTENSION_INDEX); + TNode<Object> const generator = + LoadContextElement(context, Context::EXTENSION_INDEX); SetGeneratorNotAwaiting(generator); @@ -682,7 +686,8 @@ TF_BUILTIN(AsyncGeneratorReturnClosedRejectClosure, AsyncGeneratorBuiltinsAssembler) { Node* const context = Parameter(Descriptor::kContext); Node* const value = Parameter(Descriptor::kValue); - Node* const generator = LoadContextElement(context, Context::EXTENSION_INDEX); + TNode<Object> const generator = + LoadContextElement(context, Context::EXTENSION_INDEX); SetGeneratorNotAwaiting(generator); diff --git a/deps/v8/src/builtins/builtins-async-iterator-gen.cc b/deps/v8/src/builtins/builtins-async-iterator-gen.cc index 215faa73b1..0b5c5ef8b9 100644 --- a/deps/v8/src/builtins/builtins-async-iterator-gen.cc +++ b/deps/v8/src/builtins/builtins-async-iterator-gen.cc @@ -98,7 +98,7 @@ void AsyncFromSyncBuiltinsAssembler::Generate_AsyncFromSyncIteratorMethod( 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); + TNode<NativeContext> const native_context = LoadNativeContext(context); Node* const promise = AllocateAndInitJSPromise(context); VARIABLE(var_exception, MachineRepresentation::kTagged, @@ -109,7 +109,7 @@ void AsyncFromSyncBuiltinsAssembler::Generate_AsyncFromSyncIteratorMethod( ThrowIfNotAsyncFromSyncIterator(context, iterator, &reject_promise, &var_exception, operation_name); - Node* const sync_iterator = + TNode<Object> const sync_iterator = LoadObjectField(iterator, JSAsyncFromSyncIterator::kSyncIteratorOffset); Node* const method = get_method(sync_iterator); @@ -132,13 +132,13 @@ void AsyncFromSyncBuiltinsAssembler::Generate_AsyncFromSyncIteratorMethod( 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); + TNode<JSFunction> const promise_fun = + CAST(LoadContextElement(native_context, Context::PROMISE_FUNCTION_INDEX)); CSA_ASSERT(this, IsConstructor(promise_fun)); // Let valueWrapper be PromiseResolve(%Promise%, « value »). - Node* const value_wrapper = CallBuiltin(Builtins::kPromiseResolve, - native_context, promise_fun, value); + TNode<Object> const value_wrapper = CallBuiltin( + Builtins::kPromiseResolve, native_context, promise_fun, value); // IfAbruptRejectPromise(valueWrapper, promiseCapability). GotoIfException(value_wrapper, &reject_promise, &var_exception); @@ -167,15 +167,15 @@ std::pair<Node*, Node*> AsyncFromSyncBuiltinsAssembler::LoadIteratorResult( done(this), if_notanobject(this, Label::kDeferred); GotoIf(TaggedIsSmi(iter_result), &if_notanobject); - Node* const iter_result_map = LoadMap(iter_result); + TNode<Map> const iter_result_map = LoadMap(iter_result); GotoIfNot(IsJSReceiverMap(iter_result_map), &if_notanobject); - Node* const fast_iter_result_map = + TNode<Object> const fast_iter_result_map = LoadContextElement(native_context, Context::ITERATOR_RESULT_MAP_INDEX); VARIABLE(var_value, MachineRepresentation::kTagged); VARIABLE(var_done, MachineRepresentation::kTagged); - Branch(WordEqual(iter_result_map, fast_iter_result_map), &if_fastpath, + Branch(TaggedEqual(iter_result_map, fast_iter_result_map), &if_fastpath, &if_slowpath); BIND(&if_fastpath); @@ -190,13 +190,13 @@ std::pair<Node*, Node*> AsyncFromSyncBuiltinsAssembler::LoadIteratorResult( { // Let nextDone be IteratorComplete(nextResult). // IfAbruptRejectPromise(nextDone, promiseCapability). - Node* const done = + TNode<Object> const done = GetProperty(context, iter_result, factory()->done_string()); GotoIfException(done, if_exception, var_exception); // Let nextValue be IteratorValue(nextResult). // IfAbruptRejectPromise(nextValue, promiseCapability). - Node* const value = + TNode<Object> const value = GetProperty(context, iter_result, factory()->value_string()); GotoIfException(value, if_exception, var_exception); @@ -222,7 +222,7 @@ std::pair<Node*, Node*> AsyncFromSyncBuiltinsAssembler::LoadIteratorResult( BIND(&to_boolean); { - Node* const result = + TNode<Object> const result = CallBuiltin(Builtins::kToBoolean, context, var_done.value()); var_done.Bind(result); Goto(&done); @@ -261,8 +261,8 @@ TF_BUILTIN(AsyncFromSyncIteratorPrototypeReturn, Node* const promise, Label* if_exception) { // If return is undefined, then // Let iterResult be ! CreateIterResultObject(value, true) - Node* const iter_result = CallBuiltin(Builtins::kCreateIterResultObject, - context, value, TrueConstant()); + TNode<Object> const iter_result = CallBuiltin( + Builtins::kCreateIterResultObject, context, value, TrueConstant()); // Perform ! Call(promiseCapability.[[Resolve]], undefined, « iterResult »). // IfAbruptRejectPromise(nextDone, promiseCapability). diff --git a/deps/v8/src/builtins/builtins-bigint-gen.cc b/deps/v8/src/builtins/builtins-bigint-gen.cc index d4818f0e01..691ec7f8ce 100644 --- a/deps/v8/src/builtins/builtins-bigint-gen.cc +++ b/deps/v8/src/builtins/builtins-bigint-gen.cc @@ -19,15 +19,32 @@ TF_BUILTIN(BigIntToI64, CodeStubAssembler) { TNode<Object> value = CAST(Parameter(Descriptor::kArgument)); TNode<Context> context = CAST(Parameter(Descriptor::kContext)); + TNode<BigInt> n = ToBigInt(context, value); + + TVARIABLE(UintPtrT, var_low); + TVARIABLE(UintPtrT, var_high); + + BigIntToRawBytes(n, &var_low, &var_high); + ReturnRaw(var_low.value()); +} + +// https://tc39.github.io/proposal-bigint/#sec-to-big-int64 +TF_BUILTIN(BigIntToI32Pair, CodeStubAssembler) { + if (!Is32()) { + Unreachable(); + return; + } + + TNode<Object> value = CAST(Parameter(Descriptor::kArgument)); + TNode<Context> context = CAST(Parameter(Descriptor::kContext)); TNode<BigInt> bigint = ToBigInt(context, value); TVARIABLE(UintPtrT, var_low); TVARIABLE(UintPtrT, var_high); - // 2. Let int64bit be n modulo 2^64. - // 3. If int64bit ≥ 2^63, return int64bit - 2^64; BigIntToRawBytes(bigint, &var_low, &var_high); - ReturnRaw(var_low.value()); + Return(SloppyTNode<Object>(var_low.value()), + SloppyTNode<Object>(var_high.value())); } // https://tc39.github.io/proposal-bigint/#sec-bigint-constructor-number-value @@ -43,5 +60,18 @@ TF_BUILTIN(I64ToBigInt, CodeStubAssembler) { Return(BigIntFromInt64(argument)); } +// https://tc39.github.io/proposal-bigint/#sec-bigint-constructor-number-value +TF_BUILTIN(I32PairToBigInt, CodeStubAssembler) { + if (!Is32()) { + Unreachable(); + return; + } + + TNode<IntPtrT> low = UncheckedCast<IntPtrT>(Parameter(Descriptor::kLow)); + TNode<IntPtrT> high = UncheckedCast<IntPtrT>(Parameter(Descriptor::kHigh)); + + Return(BigIntFromInt32Pair(low, high)); +} + } // namespace internal } // namespace v8 diff --git a/deps/v8/src/builtins/builtins-bigint.cc b/deps/v8/src/builtins/builtins-bigint.cc index 09d71a0562..1201ce9730 100644 --- a/deps/v8/src/builtins/builtins-bigint.cc +++ b/deps/v8/src/builtins/builtins-bigint.cc @@ -91,7 +91,7 @@ MaybeHandle<BigInt> ThisBigIntValue(Isolate* isolate, Handle<Object> value, isolate, NewTypeError(MessageTemplate::kNotGeneric, isolate->factory()->NewStringFromAsciiChecked(caller), - isolate->factory()->NewStringFromStaticChars("BigInt")), + isolate->factory()->BigInt_string()), BigInt); } diff --git a/deps/v8/src/builtins/builtins-call-gen.cc b/deps/v8/src/builtins/builtins-call-gen.cc index deb91dee24..91370b0896 100644 --- a/deps/v8/src/builtins/builtins-call-gen.cc +++ b/deps/v8/src/builtins/builtins-call-gen.cc @@ -118,15 +118,15 @@ void CallOrConstructBuiltinsAssembler::CallOrConstructWithArrayLike( GotoIf(TaggedIsSmi(arguments_list), &if_runtime); TNode<Map> arguments_list_map = LoadMap(CAST(arguments_list)); - TNode<Context> native_context = LoadNativeContext(context); + TNode<NativeContext> native_context = LoadNativeContext(context); // Check if {arguments_list} is an (unmodified) arguments object. TNode<Map> sloppy_arguments_map = CAST( LoadContextElement(native_context, Context::SLOPPY_ARGUMENTS_MAP_INDEX)); - GotoIf(WordEqual(arguments_list_map, sloppy_arguments_map), &if_arguments); + GotoIf(TaggedEqual(arguments_list_map, sloppy_arguments_map), &if_arguments); TNode<Map> strict_arguments_map = CAST( LoadContextElement(native_context, Context::STRICT_ARGUMENTS_MAP_INDEX)); - GotoIf(WordEqual(arguments_list_map, strict_arguments_map), &if_arguments); + GotoIf(TaggedEqual(arguments_list_map, strict_arguments_map), &if_arguments); // Check if {arguments_list} is a fast JSArray. Branch(IsJSArrayMap(arguments_list_map), &if_array, &if_runtime); @@ -135,10 +135,11 @@ void CallOrConstructBuiltinsAssembler::CallOrConstructWithArrayLike( TVARIABLE(Int32T, var_length); BIND(&if_array); { + TNode<JSObject> js_object = CAST(arguments_list); // Try to extract the elements from a JSArray object. - var_elements = LoadElements(CAST(arguments_list)); + var_elements = LoadElements(js_object); var_length = - LoadAndUntagToWord32ObjectField(arguments_list, JSArray::kLengthOffset); + LoadAndUntagToWord32ObjectField(js_object, JSArray::kLengthOffset); // Holey arrays and double backing stores need special treatment. STATIC_ASSERT(PACKED_SMI_ELEMENTS == 0); @@ -151,8 +152,9 @@ void CallOrConstructBuiltinsAssembler::CallOrConstructWithArrayLike( TNode<Int32T> kind = LoadMapElementsKind(arguments_list_map); - GotoIf(IsElementsKindGreaterThan(kind, LAST_FROZEN_ELEMENTS_KIND), - &if_runtime); + GotoIf( + IsElementsKindGreaterThan(kind, LAST_ANY_NONEXTENSIBLE_ELEMENTS_KIND), + &if_runtime); Branch(Word32And(kind, Int32Constant(1)), &if_holey_array, &if_done); } @@ -173,7 +175,7 @@ void CallOrConstructBuiltinsAssembler::CallOrConstructWithArrayLike( js_arguments, JSArgumentsObjectWithLength::kLengthOffset); TNode<FixedArrayBase> elements = LoadElements(js_arguments); TNode<Smi> elements_length = LoadFixedArrayBaseLength(elements); - GotoIfNot(WordEqual(length, elements_length), &if_runtime); + GotoIfNot(TaggedEqual(length, elements_length), &if_runtime); var_elements = elements; var_length = SmiToInt32(CAST(length)); Goto(&if_done); @@ -292,11 +294,11 @@ void CallOrConstructBuiltinsAssembler::CallOrConstructWithSpread( // Check that the Array.prototype hasn't been modified in a way that would // affect iteration. - TNode<PropertyCell> protector_cell = - CAST(LoadRoot(RootIndex::kArrayIteratorProtector)); - GotoIf(WordEqual(LoadObjectField(protector_cell, PropertyCell::kValueOffset), - SmiConstant(Isolate::kProtectorInvalid)), - &if_generic); + TNode<PropertyCell> protector_cell = ArrayIteratorProtectorConstant(); + GotoIf( + TaggedEqual(LoadObjectField(protector_cell, PropertyCell::kValueOffset), + SmiConstant(Isolate::kProtectorInvalid)), + &if_generic); { // The fast-path accesses the {spread} elements directly. TNode<Int32T> spread_kind = LoadMapElementsKind(spread_map); @@ -310,9 +312,9 @@ void CallOrConstructBuiltinsAssembler::CallOrConstructWithSpread( &if_smiorobject); GotoIf(IsElementsKindLessThanOrEqual(spread_kind, LAST_FAST_ELEMENTS_KIND), &if_double); - Branch( - IsElementsKindLessThanOrEqual(spread_kind, LAST_FROZEN_ELEMENTS_KIND), - &if_smiorobject, &if_generic); + Branch(IsElementsKindLessThanOrEqual(spread_kind, + LAST_ANY_NONEXTENSIBLE_ELEMENTS_KIND), + &if_smiorobject, &if_generic); } BIND(&if_generic); @@ -430,7 +432,7 @@ TNode<JSReceiver> CallOrConstructBuiltinsAssembler::GetCompatibleReceiver( // will be ruled out there). // var_template = CAST(constructor); - TNode<Int32T> template_type = LoadInstanceType(var_template.value()); + TNode<Uint16T> template_type = LoadInstanceType(var_template.value()); GotoIf(InstanceTypeEqual(template_type, JS_FUNCTION_TYPE), &template_from_closure); Branch(InstanceTypeEqual(template_type, MAP_TYPE), &template_map_loop, @@ -461,12 +463,12 @@ TNode<JSReceiver> CallOrConstructBuiltinsAssembler::GetCompatibleReceiver( // end, in which case we continue with the next holder (the // hidden prototype) if there's any. TNode<HeapObject> current = var_template.value(); - GotoIf(WordEqual(current, signature), &holder_found); + GotoIf(TaggedEqual(current, signature), &holder_found); GotoIfNot(IsFunctionTemplateInfoMap(LoadMap(current)), &holder_next); TNode<HeapObject> current_rare = LoadObjectField<HeapObject>( - current, FunctionTemplateInfo::kFunctionTemplateRareDataOffset); + current, FunctionTemplateInfo::kRareDataOffset); GotoIf(IsUndefined(current_rare), &holder_next); var_template = LoadObjectField<HeapObject>( current_rare, FunctionTemplateRareData::kParentTemplateOffset); @@ -514,7 +516,7 @@ void CallOrConstructBuiltinsAssembler::CallFunctionTemplate( GotoIfNot( IsSetWord32<Map::IsAccessCheckNeededBit>(LoadMapBitField(receiver_map)), &receiver_done); - TNode<WordT> function_template_info_flags = LoadAndUntagObjectField( + TNode<IntPtrT> function_template_info_flags = LoadAndUntagObjectField( function_template_info, FunctionTemplateInfo::kFlagOffset); Branch(IsSetWord(function_template_info_flags, 1 << FunctionTemplateInfo::kAcceptAnyReceiver), diff --git a/deps/v8/src/builtins/builtins-collections-gen.cc b/deps/v8/src/builtins/builtins-collections-gen.cc index 613e5f10ff..dec4142c65 100644 --- a/deps/v8/src/builtins/builtins-collections-gen.cc +++ b/deps/v8/src/builtins/builtins-collections-gen.cc @@ -108,8 +108,8 @@ class BaseCollectionsAssembler : public CodeStubAssembler { // Checks whether {collection}'s initial add/set function has been modified // (depending on {variant}, loaded from {native_context}). void GotoIfInitialAddFunctionModified(Variant variant, - TNode<Context> native_context, - TNode<Object> collection, + TNode<NativeContext> native_context, + TNode<HeapObject> collection, Label* if_modified); // Gets root index for the name of the add/set function. @@ -186,8 +186,8 @@ void BaseCollectionsAssembler::AddConstructorEntries( TNode<Object> table = AllocateTable(variant, context, at_least_space_for); StoreObjectField(collection, GetTableOffset(variant), table); GotoIf(IsNullOrUndefined(initial_entries), &exit); - GotoIfInitialAddFunctionModified(variant, native_context, collection, - &slow_loop); + GotoIfInitialAddFunctionModified(variant, CAST(native_context), + CAST(collection), &slow_loop); Branch(use_fast_loop.value(), &fast_loop, &slow_loop); } BIND(&fast_loop); @@ -212,15 +212,15 @@ void BaseCollectionsAssembler::AddConstructorEntries( { // Check that add/set function has not been modified. Label if_not_modified(this), if_modified(this); - GotoIfInitialAddFunctionModified(variant, native_context, collection, - &if_modified); + GotoIfInitialAddFunctionModified(variant, CAST(native_context), + CAST(collection), &if_modified); Goto(&if_not_modified); BIND(&if_modified); Unreachable(); BIND(&if_not_modified); } - CSA_ASSERT(this, WordEqual(original_initial_entries_map, - LoadMap(initial_entries_jsarray))); + CSA_ASSERT(this, TaggedEqual(original_initial_entries_map, + LoadMap(initial_entries_jsarray))); #endif use_fast_loop = Int32FalseConstant(); Goto(&allocate_table); @@ -242,9 +242,9 @@ void BaseCollectionsAssembler::AddConstructorEntriesFromFastJSArray( TNode<FixedArrayBase> elements = LoadElements(fast_jsarray); TNode<Int32T> elements_kind = LoadElementsKind(fast_jsarray); TNode<JSFunction> add_func = GetInitialAddFunction(variant, native_context); - CSA_ASSERT( - this, - WordEqual(GetAddFunction(variant, native_context, collection), add_func)); + CSA_ASSERT(this, + TaggedEqual(GetAddFunction(variant, native_context, collection), + add_func)); CSA_ASSERT(this, IsFastJSArrayWithNoCustomIteration(context, fast_jsarray)); TNode<IntPtrT> length = SmiUntag(LoadFastJSArrayLength(fast_jsarray)); CSA_ASSERT(this, IntPtrGreaterThanOrEqual(length, IntPtrConstant(0))); @@ -301,9 +301,9 @@ void BaseCollectionsAssembler::AddConstructorEntriesFromFastJSArray( BIND(&exit); #if DEBUG CSA_ASSERT(this, - WordEqual(original_collection_map, LoadMap(CAST(collection)))); + TaggedEqual(original_collection_map, LoadMap(CAST(collection)))); CSA_ASSERT(this, - WordEqual(original_fast_js_array_map, LoadMap(fast_jsarray))); + TaggedEqual(original_fast_js_array_map, LoadMap(fast_jsarray))); #endif } @@ -356,21 +356,44 @@ RootIndex BaseCollectionsAssembler::GetAddFunctionNameIndex(Variant variant) { } void BaseCollectionsAssembler::GotoIfInitialAddFunctionModified( - Variant variant, TNode<Context> native_context, TNode<Object> collection, - Label* if_modified) { + Variant variant, TNode<NativeContext> native_context, + TNode<HeapObject> collection, Label* if_modified) { STATIC_ASSERT(JSCollection::kAddFunctionDescriptorIndex == JSWeakCollection::kAddFunctionDescriptorIndex); - GotoIfInitialPrototypePropertyModified( - LoadMap(CAST(collection)), - GetInitialCollectionPrototype(variant, native_context), + + // TODO(jgruber): Investigate if this should also fall back to full prototype + // verification. + static constexpr PrototypeCheckAssembler::Flags flags{ + PrototypeCheckAssembler::kCheckPrototypePropertyConstness}; + + static constexpr int kNoContextIndex = -1; + STATIC_ASSERT( + (flags & PrototypeCheckAssembler::kCheckPrototypePropertyIdentity) == 0); + + using DescriptorIndexNameValue = + PrototypeCheckAssembler::DescriptorIndexNameValue; + + DescriptorIndexNameValue property_to_check{ JSCollection::kAddFunctionDescriptorIndex, - GetAddFunctionNameIndex(variant), if_modified); + GetAddFunctionNameIndex(variant), kNoContextIndex}; + + PrototypeCheckAssembler prototype_check_assembler( + state(), flags, native_context, + GetInitialCollectionPrototype(variant, native_context), + Vector<DescriptorIndexNameValue>(&property_to_check, 1)); + + TNode<HeapObject> prototype = LoadMapPrototype(LoadMap(collection)); + Label if_unmodified(this); + prototype_check_assembler.CheckAndBranch(prototype, &if_unmodified, + if_modified); + + BIND(&if_unmodified); } TNode<JSObject> BaseCollectionsAssembler::AllocateJSCollection( TNode<Context> context, TNode<JSFunction> constructor, TNode<JSReceiver> new_target) { - TNode<BoolT> is_target_unmodified = WordEqual(constructor, new_target); + TNode<BoolT> is_target_unmodified = TaggedEqual(constructor, new_target); return Select<JSObject>( is_target_unmodified, @@ -406,8 +429,8 @@ void BaseCollectionsAssembler::GenerateConstructor( Label if_undefined(this, Label::kDeferred); GotoIf(IsUndefined(new_target), &if_undefined); - TNode<Context> native_context = LoadNativeContext(context); - TNode<Object> collection = AllocateJSCollection( + TNode<NativeContext> native_context = LoadNativeContext(context); + TNode<JSObject> collection = AllocateJSCollection( context, GetConstructor(variant, native_context), CAST(new_target)); AddConstructorEntries(variant, context, native_context, collection, iterable); @@ -531,8 +554,8 @@ TNode<BoolT> BaseCollectionsAssembler::HasInitialCollectionPrototype( TNode<Map> collection_proto_map = LoadMap(LoadMapPrototype(LoadMap(CAST(collection)))); - return WordEqual(collection_proto_map, - GetInitialCollectionPrototype(variant, native_context)); + return TaggedEqual(collection_proto_map, + GetInitialCollectionPrototype(variant, native_context)); } TNode<Object> BaseCollectionsAssembler::LoadAndNormalizeFixedArrayElement( @@ -585,13 +608,13 @@ class CollectionsBuiltinsAssembler : public BaseCollectionsAssembler { protected: template <typename IteratorType> - Node* AllocateJSCollectionIterator(Node* context, int map_index, - Node* collection); + Node* AllocateJSCollectionIterator(SloppyTNode<Context> context, + int map_index, Node* collection); TNode<Object> AllocateTable(Variant variant, TNode<Context> context, TNode<IntPtrT> at_least_space_for) override; - Node* GetHash(Node* const key); - Node* CallGetHashRaw(Node* const key); - Node* CallGetOrCreateHashRaw(Node* const key); + TNode<IntPtrT> GetHash(SloppyTNode<HeapObject> const key); + TNode<IntPtrT> CallGetHashRaw(SloppyTNode<HeapObject> const key); + TNode<Smi> CallGetOrCreateHashRaw(SloppyTNode<HeapObject> const key); // Transitions the iterator to the non obsolete backing store. // This is a NOP if the [table] is not obsolete. @@ -612,23 +635,25 @@ class CollectionsBuiltinsAssembler : public BaseCollectionsAssembler { // The {result} variable will contain the entry index if the key was found, // or the hash code otherwise. template <typename CollectionType> - void FindOrderedHashTableEntryForSmiKey(Node* table, Node* key_tagged, + void FindOrderedHashTableEntryForSmiKey(Node* table, + SloppyTNode<Smi> key_tagged, Variable* result, Label* entry_found, Label* not_found); - void SameValueZeroSmi(Node* key_smi, Node* candidate_key, Label* if_same, + void SameValueZeroSmi(SloppyTNode<Smi> key_smi, + SloppyTNode<Object> candidate_key, Label* if_same, Label* if_not_same); // Specialization for heap numbers. // The {result} variable will contain the entry index if the key was found, // or the hash code otherwise. - void SameValueZeroHeapNumber(Node* key_string, Node* candidate_key, + void SameValueZeroHeapNumber(SloppyTNode<Float64T> key_float, + SloppyTNode<Object> candidate_key, Label* if_same, Label* if_not_same); template <typename CollectionType> - void FindOrderedHashTableEntryForHeapNumberKey(Node* context, Node* table, - Node* key_heap_number, - Variable* result, - Label* entry_found, - Label* not_found); + void FindOrderedHashTableEntryForHeapNumberKey( + SloppyTNode<Context> context, Node* table, + SloppyTNode<HeapNumber> key_heap_number, Variable* result, + Label* entry_found, Label* not_found); // Specialization for bigints. // The {result} variable will contain the entry index if the key was found, @@ -636,8 +661,9 @@ class CollectionsBuiltinsAssembler : public BaseCollectionsAssembler { void SameValueZeroBigInt(Node* key, Node* candidate_key, Label* if_same, Label* if_not_same); template <typename CollectionType> - void FindOrderedHashTableEntryForBigIntKey(Node* context, Node* table, - Node* key, Variable* result, + void FindOrderedHashTableEntryForBigIntKey(SloppyTNode<Context> context, + Node* table, Node* key, + Variable* result, Label* entry_found, Label* not_found); @@ -645,13 +671,15 @@ class CollectionsBuiltinsAssembler : public BaseCollectionsAssembler { // The {result} variable will contain the entry index if the key was found, // or the hash code otherwise. template <typename CollectionType> - void FindOrderedHashTableEntryForStringKey(Node* context, Node* table, - Node* key_tagged, Variable* result, - Label* entry_found, - Label* not_found); - Node* ComputeStringHash(Node* context, Node* string_key); - void SameValueZeroString(Node* context, Node* key_string, Node* candidate_key, - Label* if_same, Label* if_not_same); + void FindOrderedHashTableEntryForStringKey( + SloppyTNode<Context> context, Node* table, SloppyTNode<String> key_tagged, + Variable* result, Label* entry_found, Label* not_found); + TNode<IntPtrT> ComputeStringHash(TNode<Context> context, + TNode<String> string_key); + void SameValueZeroString(SloppyTNode<Context> context, + SloppyTNode<String> key_string, + SloppyTNode<Object> candidate_key, Label* if_same, + Label* if_not_same); // Specialization for non-strings, non-numbers. For those we only need // reference equality to compare the keys. @@ -659,10 +687,9 @@ class CollectionsBuiltinsAssembler : public BaseCollectionsAssembler { // or the hash code otherwise. If the hash-code has not been computed, it // should be Smi -1. template <typename CollectionType> - void FindOrderedHashTableEntryForOtherKey(Node* context, Node* table, - Node* key, Variable* result, - Label* entry_found, - Label* not_found); + void FindOrderedHashTableEntryForOtherKey( + SloppyTNode<Context> context, Node* table, SloppyTNode<HeapObject> key, + Variable* result, Label* entry_found, Label* not_found); template <typename CollectionType> void TryLookupOrderedHashTableIndex(Node* const table, Node* const key, @@ -704,11 +731,13 @@ class CollectionsBuiltinsAssembler : public BaseCollectionsAssembler { template <typename IteratorType> Node* CollectionsBuiltinsAssembler::AllocateJSCollectionIterator( - Node* context, int map_index, Node* collection) { - Node* const table = LoadObjectField(collection, JSCollection::kTableOffset); - Node* const native_context = LoadNativeContext(context); - Node* const iterator_map = LoadContextElement(native_context, map_index); - Node* const iterator = AllocateInNewSpace(IteratorType::kSize); + SloppyTNode<Context> context, int map_index, Node* collection) { + TNode<Object> const table = + LoadObjectField(collection, JSCollection::kTableOffset); + TNode<NativeContext> const native_context = LoadNativeContext(context); + TNode<Object> const iterator_map = + LoadContextElement(native_context, map_index); + TNode<HeapObject> const iterator = AllocateInNewSpace(IteratorType::kSize); StoreMapNoWriteBarrier(iterator, iterator_map); StoreObjectFieldRoot(iterator, IteratorType::kPropertiesOrHashOffset, RootIndex::kEmptyFixedArray); @@ -748,10 +777,11 @@ TF_BUILTIN(SetConstructor, CollectionsBuiltinsAssembler) { argc, context); } -Node* CollectionsBuiltinsAssembler::CallGetOrCreateHashRaw(Node* const key) { - Node* const function_addr = +TNode<Smi> CollectionsBuiltinsAssembler::CallGetOrCreateHashRaw( + SloppyTNode<HeapObject> const key) { + TNode<ExternalReference> const function_addr = ExternalConstant(ExternalReference::get_or_create_hash_raw()); - Node* const isolate_ptr = + TNode<ExternalReference> const isolate_ptr = ExternalConstant(ExternalReference::isolate_address(isolate())); MachineType type_ptr = MachineType::Pointer(); @@ -761,13 +791,14 @@ Node* CollectionsBuiltinsAssembler::CallGetOrCreateHashRaw(Node* const key) { std::make_pair(type_ptr, isolate_ptr), std::make_pair(type_tagged, key)); - return result; + return CAST(result); } -Node* CollectionsBuiltinsAssembler::CallGetHashRaw(Node* const key) { - Node* const function_addr = +TNode<IntPtrT> CollectionsBuiltinsAssembler::CallGetHashRaw( + SloppyTNode<HeapObject> const key) { + TNode<ExternalReference> const function_addr = ExternalConstant(ExternalReference::orderedhashmap_gethash_raw()); - Node* const isolate_ptr = + TNode<ExternalReference> const isolate_ptr = ExternalConstant(ExternalReference::isolate_address(isolate())); MachineType type_ptr = MachineType::Pointer(); @@ -780,20 +811,21 @@ Node* CollectionsBuiltinsAssembler::CallGetHashRaw(Node* const key) { return SmiUntag(result); } -Node* CollectionsBuiltinsAssembler::GetHash(Node* const key) { - VARIABLE(var_hash, MachineType::PointerRepresentation()); +TNode<IntPtrT> CollectionsBuiltinsAssembler::GetHash( + SloppyTNode<HeapObject> const key) { + TVARIABLE(IntPtrT, var_hash); Label if_receiver(this), if_other(this), done(this); Branch(IsJSReceiver(key), &if_receiver, &if_other); BIND(&if_receiver); { - var_hash.Bind(LoadJSReceiverIdentityHash(key)); + var_hash = LoadJSReceiverIdentityHash(key); Goto(&done); } BIND(&if_other); { - var_hash.Bind(CallGetHashRaw(key)); + var_hash = CallGetHashRaw(key); Goto(&done); } @@ -801,12 +833,11 @@ Node* CollectionsBuiltinsAssembler::GetHash(Node* const key) { return var_hash.value(); } -void CollectionsBuiltinsAssembler::SameValueZeroSmi(Node* key_smi, - Node* candidate_key, - Label* if_same, - Label* if_not_same) { +void CollectionsBuiltinsAssembler::SameValueZeroSmi( + SloppyTNode<Smi> key_smi, SloppyTNode<Object> candidate_key, Label* if_same, + Label* if_not_same) { // If the key is the same, we are done. - GotoIf(WordEqual(candidate_key, key_smi), if_same); + GotoIf(TaggedEqual(candidate_key, key_smi), if_same); // If the candidate key is smi, then it must be different (because // we already checked for equality above). @@ -814,10 +845,11 @@ void CollectionsBuiltinsAssembler::SameValueZeroSmi(Node* key_smi, // If the candidate key is not smi, we still have to check if it is a // heap number with the same value. - GotoIfNot(IsHeapNumber(candidate_key), if_not_same); + GotoIfNot(IsHeapNumber(CAST(candidate_key)), if_not_same); - Node* const candidate_key_number = LoadHeapNumberValue(candidate_key); - Node* const key_number = SmiToFloat64(key_smi); + TNode<Float64T> const candidate_key_number = + LoadHeapNumberValue(CAST(candidate_key)); + TNode<Float64T> const key_number = SmiToFloat64(key_smi); GotoIf(Float64Equal(candidate_key_number, key_number), if_same); @@ -826,11 +858,12 @@ void CollectionsBuiltinsAssembler::SameValueZeroSmi(Node* key_smi, void CollectionsBuiltinsAssembler::BranchIfMapIteratorProtectorValid( Label* if_true, Label* if_false) { - Node* protector_cell = LoadRoot(RootIndex::kMapIteratorProtector); + TNode<PropertyCell> protector_cell = MapIteratorProtectorConstant(); DCHECK(isolate()->heap()->map_iterator_protector().IsPropertyCell()); - Branch(WordEqual(LoadObjectField(protector_cell, PropertyCell::kValueOffset), - SmiConstant(Isolate::kProtectorValid)), - if_true, if_false); + Branch( + TaggedEqual(LoadObjectField(protector_cell, PropertyCell::kValueOffset), + SmiConstant(Isolate::kProtectorValid)), + if_true, if_false); } void CollectionsBuiltinsAssembler:: @@ -843,7 +876,7 @@ void CollectionsBuiltinsAssembler:: // Check if iterator is a keys or values JSMapIterator. GotoIf(TaggedIsSmi(iterator), if_false); TNode<Map> iter_map = LoadMap(CAST(iterator)); - Node* const instance_type = LoadMapInstanceType(iter_map); + TNode<Uint16T> const instance_type = LoadMapInstanceType(iter_map); GotoIf(InstanceTypeEqual(instance_type, JS_MAP_KEY_ITERATOR_TYPE), &if_key_or_value_iterator); Branch(InstanceTypeEqual(instance_type, JS_MAP_VALUE_ITERATOR_TYPE), @@ -851,25 +884,26 @@ void CollectionsBuiltinsAssembler:: BIND(&if_key_or_value_iterator); // Check that the iterator is not partially consumed. - Node* const index = + TNode<Object> const index = LoadObjectField(CAST(iterator), JSMapIterator::kIndexOffset); - GotoIfNot(WordEqual(index, SmiConstant(0)), if_false); + GotoIfNot(TaggedEqual(index, SmiConstant(0)), if_false); BranchIfMapIteratorProtectorValid(&extra_checks, if_false); BIND(&extra_checks); // Check if the iterator object has the original %MapIteratorPrototype%. - Node* const native_context = LoadNativeContext(context); - Node* const initial_map_iter_proto = LoadContextElement( + TNode<NativeContext> const native_context = LoadNativeContext(context); + TNode<Object> const initial_map_iter_proto = LoadContextElement( native_context, Context::INITIAL_MAP_ITERATOR_PROTOTYPE_INDEX); - Node* const map_iter_proto = LoadMapPrototype(iter_map); - GotoIfNot(WordEqual(map_iter_proto, initial_map_iter_proto), if_false); + TNode<HeapObject> const map_iter_proto = LoadMapPrototype(iter_map); + GotoIfNot(TaggedEqual(map_iter_proto, initial_map_iter_proto), if_false); // Check if the original MapIterator prototype has the original // %IteratorPrototype%. - Node* const initial_iter_proto = LoadContextElement( + TNode<Object> const initial_iter_proto = LoadContextElement( native_context, Context::INITIAL_ITERATOR_PROTOTYPE_INDEX); - Node* const iter_proto = LoadMapPrototype(LoadMap(map_iter_proto)); - Branch(WordEqual(iter_proto, initial_iter_proto), if_true, if_false); + TNode<HeapObject> const iter_proto = + LoadMapPrototype(LoadMap(map_iter_proto)); + Branch(TaggedEqual(iter_proto, initial_iter_proto), if_true, if_false); } void BranchIfIterableWithOriginalKeyOrValueMapIterator( @@ -883,11 +917,12 @@ void BranchIfIterableWithOriginalKeyOrValueMapIterator( void CollectionsBuiltinsAssembler::BranchIfSetIteratorProtectorValid( Label* if_true, Label* if_false) { - Node* const protector_cell = LoadRoot(RootIndex::kSetIteratorProtector); + TNode<PropertyCell> const protector_cell = SetIteratorProtectorConstant(); DCHECK(isolate()->heap()->set_iterator_protector().IsPropertyCell()); - Branch(WordEqual(LoadObjectField(protector_cell, PropertyCell::kValueOffset), - SmiConstant(Isolate::kProtectorValid)), - if_true, if_false); + Branch( + TaggedEqual(LoadObjectField(protector_cell, PropertyCell::kValueOffset), + SmiConstant(Isolate::kProtectorValid)), + if_true, if_false); } void CollectionsBuiltinsAssembler::BranchIfIterableWithOriginalValueSetIterator( @@ -898,7 +933,7 @@ void CollectionsBuiltinsAssembler::BranchIfIterableWithOriginalValueSetIterator( GotoIf(TaggedIsSmi(iterable), if_false); TNode<Map> iterable_map = LoadMap(CAST(iterable)); - Node* const instance_type = LoadMapInstanceType(iterable_map); + TNode<Uint16T> const instance_type = LoadMapInstanceType(iterable_map); GotoIf(InstanceTypeEqual(instance_type, JS_SET_TYPE), &if_set); Branch(InstanceTypeEqual(instance_type, JS_SET_VALUE_ITERATOR_TYPE), @@ -906,31 +941,32 @@ void CollectionsBuiltinsAssembler::BranchIfIterableWithOriginalValueSetIterator( BIND(&if_set); // Check if the set object has the original Set prototype. - Node* const initial_set_proto = LoadContextElement( + TNode<Object> const initial_set_proto = LoadContextElement( LoadNativeContext(context), Context::INITIAL_SET_PROTOTYPE_INDEX); - Node* const set_proto = LoadMapPrototype(iterable_map); - GotoIfNot(WordEqual(set_proto, initial_set_proto), if_false); + TNode<HeapObject> const set_proto = LoadMapPrototype(iterable_map); + GotoIfNot(TaggedEqual(set_proto, initial_set_proto), if_false); Goto(&check_protector); BIND(&if_value_iterator); // Check that the iterator is not partially consumed. - Node* const index = + TNode<Object> const index = LoadObjectField(CAST(iterable), JSSetIterator::kIndexOffset); - GotoIfNot(WordEqual(index, SmiConstant(0)), if_false); + GotoIfNot(TaggedEqual(index, SmiConstant(0)), if_false); // Check if the iterator object has the original SetIterator prototype. - Node* const native_context = LoadNativeContext(context); - Node* const initial_set_iter_proto = LoadContextElement( + TNode<NativeContext> const native_context = LoadNativeContext(context); + TNode<Object> const initial_set_iter_proto = LoadContextElement( native_context, Context::INITIAL_SET_ITERATOR_PROTOTYPE_INDEX); - Node* const set_iter_proto = LoadMapPrototype(iterable_map); - GotoIfNot(WordEqual(set_iter_proto, initial_set_iter_proto), if_false); + TNode<HeapObject> const set_iter_proto = LoadMapPrototype(iterable_map); + GotoIfNot(TaggedEqual(set_iter_proto, initial_set_iter_proto), if_false); // Check if the original SetIterator prototype has the original // %IteratorPrototype%. - Node* const initial_iter_proto = LoadContextElement( + TNode<Object> const initial_iter_proto = LoadContextElement( native_context, Context::INITIAL_ITERATOR_PROTOTYPE_INDEX); - Node* const iter_proto = LoadMapPrototype(LoadMap(set_iter_proto)); - GotoIfNot(WordEqual(iter_proto, initial_iter_proto), if_false); + TNode<HeapObject> const iter_proto = + LoadMapPrototype(LoadMap(set_iter_proto)); + GotoIfNot(TaggedEqual(iter_proto, initial_iter_proto), if_false); Goto(&check_protector); BIND(&check_protector); @@ -1043,7 +1079,7 @@ TNode<JSArray> CollectionsBuiltinsAssembler::SetOrSetIteratorToList( TVARIABLE(OrderedHashSet, var_table); Label if_set(this), if_iterator(this), copy(this); - Node* const instance_type = LoadInstanceType(CAST(iterable)); + TNode<Uint16T> const instance_type = LoadInstanceType(CAST(iterable)); Branch(InstanceTypeEqual(instance_type, JS_SET_TYPE), &if_set, &if_iterator); BIND(&if_set); @@ -1128,15 +1164,16 @@ TF_BUILTIN(SetOrSetIteratorToList, CollectionsBuiltinsAssembler) { template <typename CollectionType> void CollectionsBuiltinsAssembler::FindOrderedHashTableEntryForSmiKey( - Node* table, Node* smi_key, Variable* result, Label* entry_found, + Node* table, SloppyTNode<Smi> smi_key, Variable* result, Label* entry_found, Label* not_found) { - Node* const key_untagged = SmiUntag(smi_key); - Node* const hash = ChangeInt32ToIntPtr(ComputeUnseededHash(key_untagged)); + TNode<IntPtrT> const key_untagged = SmiUntag(smi_key); + TNode<IntPtrT> const hash = + ChangeInt32ToIntPtr(ComputeUnseededHash(key_untagged)); CSA_ASSERT(this, IntPtrGreaterThanOrEqual(hash, IntPtrConstant(0))); result->Bind(hash); FindOrderedHashTableEntry<CollectionType>( table, hash, - [&](Node* other_key, Label* if_same, Label* if_not_same) { + [&](TNode<Object> other_key, Label* if_same, Label* if_not_same) { SameValueZeroSmi(smi_key, other_key, if_same, if_not_same); }, result, entry_found, not_found); @@ -1144,14 +1181,14 @@ void CollectionsBuiltinsAssembler::FindOrderedHashTableEntryForSmiKey( template <typename CollectionType> void CollectionsBuiltinsAssembler::FindOrderedHashTableEntryForStringKey( - Node* context, Node* table, Node* key_tagged, Variable* result, - Label* entry_found, Label* not_found) { - Node* const hash = ComputeStringHash(context, key_tagged); + SloppyTNode<Context> context, Node* table, SloppyTNode<String> key_tagged, + Variable* result, Label* entry_found, Label* not_found) { + TNode<IntPtrT> const hash = ComputeStringHash(context, key_tagged); CSA_ASSERT(this, IntPtrGreaterThanOrEqual(hash, IntPtrConstant(0))); result->Bind(hash); FindOrderedHashTableEntry<CollectionType>( table, hash, - [&](Node* other_key, Label* if_same, Label* if_not_same) { + [&](TNode<Object> other_key, Label* if_same, Label* if_not_same) { SameValueZeroString(context, key_tagged, other_key, if_same, if_not_same); }, @@ -1160,15 +1197,16 @@ void CollectionsBuiltinsAssembler::FindOrderedHashTableEntryForStringKey( template <typename CollectionType> void CollectionsBuiltinsAssembler::FindOrderedHashTableEntryForHeapNumberKey( - Node* context, Node* table, Node* key_heap_number, Variable* result, + SloppyTNode<Context> context, Node* table, + SloppyTNode<HeapNumber> key_heap_number, Variable* result, Label* entry_found, Label* not_found) { - Node* hash = CallGetHashRaw(key_heap_number); + TNode<IntPtrT> const hash = CallGetHashRaw(key_heap_number); CSA_ASSERT(this, IntPtrGreaterThanOrEqual(hash, IntPtrConstant(0))); result->Bind(hash); - Node* const key_float = LoadHeapNumberValue(key_heap_number); + TNode<Float64T> const key_float = LoadHeapNumberValue(key_heap_number); FindOrderedHashTableEntry<CollectionType>( table, hash, - [&](Node* other_key, Label* if_same, Label* if_not_same) { + [&](TNode<Object> other_key, Label* if_same, Label* if_not_same) { SameValueZeroHeapNumber(key_float, other_key, if_same, if_not_same); }, result, entry_found, not_found); @@ -1176,14 +1214,14 @@ void CollectionsBuiltinsAssembler::FindOrderedHashTableEntryForHeapNumberKey( template <typename CollectionType> void CollectionsBuiltinsAssembler::FindOrderedHashTableEntryForBigIntKey( - Node* context, Node* table, Node* key, Variable* result, Label* entry_found, - Label* not_found) { - Node* hash = CallGetHashRaw(key); + SloppyTNode<Context> context, Node* table, Node* key, Variable* result, + Label* entry_found, Label* not_found) { + TNode<IntPtrT> const hash = CallGetHashRaw(key); CSA_ASSERT(this, IntPtrGreaterThanOrEqual(hash, IntPtrConstant(0))); result->Bind(hash); FindOrderedHashTableEntry<CollectionType>( table, hash, - [&](Node* other_key, Label* if_same, Label* if_not_same) { + [&](TNode<Object> other_key, Label* if_same, Label* if_not_same) { SameValueZeroBigInt(key, other_key, if_same, if_not_same); }, result, entry_found, not_found); @@ -1191,49 +1229,47 @@ void CollectionsBuiltinsAssembler::FindOrderedHashTableEntryForBigIntKey( template <typename CollectionType> void CollectionsBuiltinsAssembler::FindOrderedHashTableEntryForOtherKey( - Node* context, Node* table, Node* key, Variable* result, Label* entry_found, - Label* not_found) { - Node* hash = GetHash(key); + SloppyTNode<Context> context, Node* table, SloppyTNode<HeapObject> key, + Variable* result, Label* entry_found, Label* not_found) { + TNode<IntPtrT> const hash = GetHash(key); CSA_ASSERT(this, IntPtrGreaterThanOrEqual(hash, IntPtrConstant(0))); result->Bind(hash); FindOrderedHashTableEntry<CollectionType>( table, hash, - [&](Node* other_key, Label* if_same, Label* if_not_same) { - Branch(WordEqual(key, other_key), if_same, if_not_same); + [&](TNode<Object> other_key, Label* if_same, Label* if_not_same) { + Branch(TaggedEqual(key, other_key), if_same, if_not_same); }, result, entry_found, not_found); } -Node* CollectionsBuiltinsAssembler::ComputeStringHash(Node* context, - Node* string_key) { - VARIABLE(var_result, MachineType::PointerRepresentation()); +TNode<IntPtrT> CollectionsBuiltinsAssembler::ComputeStringHash( + TNode<Context> context, TNode<String> string_key) { + TVARIABLE(IntPtrT, var_result); Label hash_not_computed(this), done(this, &var_result); - Node* hash = + TNode<IntPtrT> const hash = ChangeInt32ToIntPtr(LoadNameHash(string_key, &hash_not_computed)); - var_result.Bind(hash); + var_result = hash; Goto(&done); BIND(&hash_not_computed); - var_result.Bind(CallGetHashRaw(string_key)); + var_result = CallGetHashRaw(string_key); Goto(&done); BIND(&done); return var_result.value(); } -void CollectionsBuiltinsAssembler::SameValueZeroString(Node* context, - Node* key_string, - Node* candidate_key, - Label* if_same, - Label* if_not_same) { +void CollectionsBuiltinsAssembler::SameValueZeroString( + SloppyTNode<Context> context, SloppyTNode<String> key_string, + SloppyTNode<Object> candidate_key, Label* if_same, Label* if_not_same) { // If the candidate is not a string, the keys are not equal. GotoIf(TaggedIsSmi(candidate_key), if_not_same); - GotoIfNot(IsString(candidate_key), if_not_same); + GotoIfNot(IsString(CAST(candidate_key)), if_not_same); - Branch(WordEqual(CallBuiltin(Builtins::kStringEqual, context, key_string, - candidate_key), - TrueConstant()), + Branch(TaggedEqual(CallBuiltin(Builtins::kStringEqual, context, key_string, + candidate_key), + TrueConstant()), if_same, if_not_same); } @@ -1245,24 +1281,24 @@ void CollectionsBuiltinsAssembler::SameValueZeroBigInt(Node* key, GotoIf(TaggedIsSmi(candidate_key), if_not_same); GotoIfNot(IsBigInt(candidate_key), if_not_same); - Branch(WordEqual(CallRuntime(Runtime::kBigIntEqualToBigInt, - NoContextConstant(), key, candidate_key), - TrueConstant()), + Branch(TaggedEqual(CallRuntime(Runtime::kBigIntEqualToBigInt, + NoContextConstant(), key, candidate_key), + TrueConstant()), if_same, if_not_same); } -void CollectionsBuiltinsAssembler::SameValueZeroHeapNumber(Node* key_float, - Node* candidate_key, - Label* if_same, - Label* if_not_same) { +void CollectionsBuiltinsAssembler::SameValueZeroHeapNumber( + SloppyTNode<Float64T> key_float, SloppyTNode<Object> candidate_key, + Label* if_same, Label* if_not_same) { Label if_smi(this), if_keyisnan(this); GotoIf(TaggedIsSmi(candidate_key), &if_smi); - GotoIfNot(IsHeapNumber(candidate_key), if_not_same); + GotoIfNot(IsHeapNumber(CAST(candidate_key)), if_not_same); { // {candidate_key} is a heap number. - Node* const candidate_float = LoadHeapNumberValue(candidate_key); + TNode<Float64T> const candidate_float = + LoadHeapNumberValue(CAST(candidate_key)); GotoIf(Float64Equal(key_float, candidate_float), if_same); // SameValueZero needs to treat NaNs as equal. First check if {key_float} @@ -1279,7 +1315,7 @@ void CollectionsBuiltinsAssembler::SameValueZeroHeapNumber(Node* key_float, BIND(&if_smi); { - Node* const candidate_float = SmiToFloat64(candidate_key); + TNode<Float64T> const candidate_float = SmiToFloat64(CAST(candidate_key)); Branch(Float64Equal(key_float, candidate_float), if_same, if_not_same); } } @@ -1295,12 +1331,12 @@ TF_BUILTIN(OrderedHashTableHealIndex, CollectionsBuiltinsAssembler) { // Check if the {table} was cleared. STATIC_ASSERT(OrderedHashMap::NumberOfDeletedElementsOffset() == OrderedHashSet::NumberOfDeletedElementsOffset()); - Node* number_of_deleted_elements = LoadAndUntagObjectField( + TNode<IntPtrT> number_of_deleted_elements = LoadAndUntagObjectField( table, OrderedHashMap::NumberOfDeletedElementsOffset()); STATIC_ASSERT(OrderedHashMap::kClearedTableSentinel == OrderedHashSet::kClearedTableSentinel); - GotoIf(WordEqual(number_of_deleted_elements, - IntPtrConstant(OrderedHashMap::kClearedTableSentinel)), + GotoIf(IntPtrEqual(number_of_deleted_elements, + IntPtrConstant(OrderedHashMap::kClearedTableSentinel)), &return_zero); VARIABLE(var_i, MachineType::PointerRepresentation(), IntPtrConstant(0)); @@ -1430,7 +1466,7 @@ TF_BUILTIN(MapPrototypeGet, CollectionsBuiltinsAssembler) { ThrowIfNotInstanceType(context, receiver, JS_MAP_TYPE, "Map.prototype.get"); - Node* const table = LoadObjectField(receiver, JSMap::kTableOffset); + TNode<Object> const table = LoadObjectField(receiver, JSMap::kTableOffset); TNode<Smi> index = CAST( CallBuiltin(Builtins::kFindOrderedHashMapEntry, context, table, key)); @@ -1455,7 +1491,7 @@ TF_BUILTIN(MapPrototypeHas, CollectionsBuiltinsAssembler) { ThrowIfNotInstanceType(context, receiver, JS_MAP_TYPE, "Map.prototype.has"); - Node* const table = LoadObjectField(receiver, JSMap::kTableOffset); + TNode<Object> const table = LoadObjectField(receiver, JSMap::kTableOffset); TNode<Smi> index = CAST( CallBuiltin(Builtins::kFindOrderedHashMapEntry, context, table, key)); @@ -1476,7 +1512,7 @@ Node* CollectionsBuiltinsAssembler::NormalizeNumberKey(Node* const key) { GotoIf(TaggedIsSmi(key), &done); GotoIfNot(IsHeapNumber(key), &done); - Node* const number = LoadHeapNumberValue(key); + TNode<Float64T> const number = LoadHeapNumberValue(key); GotoIfNot(Float64Equal(number, Float64Constant(0.0)), &done); // We know the value is zero, so we take the key to be Smi 0. // Another option would be to normalize to Smi here. @@ -1539,10 +1575,10 @@ TF_BUILTIN(MapPrototypeSet, CollectionsBuiltinsAssembler) { table, OrderedHashMap::NumberOfBucketsIndex())))); STATIC_ASSERT(OrderedHashMap::kLoadFactor == 2); - Node* const capacity = WordShl(number_of_buckets.value(), 1); - Node* const number_of_elements = SmiUntag( + TNode<WordT> const capacity = WordShl(number_of_buckets.value(), 1); + TNode<IntPtrT> const number_of_elements = SmiUntag( CAST(LoadObjectField(table, OrderedHashMap::NumberOfElementsOffset()))); - Node* const number_of_deleted = SmiUntag(CAST(LoadObjectField( + TNode<IntPtrT> const number_of_deleted = SmiUntag(CAST(LoadObjectField( table, OrderedHashMap::NumberOfDeletedElementsOffset()))); occupancy.Bind(IntPtrAdd(number_of_elements, number_of_deleted)); GotoIf(IntPtrLessThan(occupancy.value(), capacity), &store_new_entry); @@ -1553,9 +1589,9 @@ TF_BUILTIN(MapPrototypeSet, CollectionsBuiltinsAssembler) { table_var = CAST(LoadObjectField(receiver, JSMap::kTableOffset)); number_of_buckets.Bind(SmiUntag(CAST(UnsafeLoadFixedArrayElement( table_var.value(), OrderedHashMap::NumberOfBucketsIndex())))); - Node* const new_number_of_elements = SmiUntag(CAST(LoadObjectField( + TNode<IntPtrT> const new_number_of_elements = SmiUntag(CAST(LoadObjectField( table_var.value(), OrderedHashMap::NumberOfElementsOffset()))); - Node* const new_number_of_deleted = SmiUntag(CAST(LoadObjectField( + TNode<IntPtrT> const new_number_of_deleted = SmiUntag(CAST(LoadObjectField( table_var.value(), OrderedHashMap::NumberOfDeletedElementsOffset()))); occupancy.Bind(IntPtrAdd(new_number_of_elements, new_number_of_deleted)); Goto(&store_new_entry); @@ -1571,13 +1607,13 @@ TF_BUILTIN(MapPrototypeSet, CollectionsBuiltinsAssembler) { void CollectionsBuiltinsAssembler::StoreOrderedHashMapNewEntry( TNode<OrderedHashMap> const table, Node* const key, Node* const value, Node* const hash, Node* const number_of_buckets, Node* const occupancy) { - Node* const bucket = + TNode<WordT> const bucket = WordAnd(hash, IntPtrSub(number_of_buckets, IntPtrConstant(1))); TNode<Smi> bucket_entry = CAST(UnsafeLoadFixedArrayElement( table, bucket, OrderedHashMap::HashTableStartIndex() * kTaggedSize)); // Store the entry elements. - Node* const entry_start = IntPtrAdd( + TNode<WordT> const entry_start = IntPtrAdd( IntPtrMul(occupancy, IntPtrConstant(OrderedHashMap::kEntrySize)), number_of_buckets); UnsafeStoreFixedArrayElement( @@ -1713,10 +1749,10 @@ TF_BUILTIN(SetPrototypeAdd, CollectionsBuiltinsAssembler) { table, OrderedHashSet::NumberOfBucketsIndex())))); STATIC_ASSERT(OrderedHashSet::kLoadFactor == 2); - Node* const capacity = WordShl(number_of_buckets.value(), 1); - Node* const number_of_elements = SmiUntag( + TNode<WordT> const capacity = WordShl(number_of_buckets.value(), 1); + TNode<IntPtrT> const number_of_elements = SmiUntag( CAST(LoadObjectField(table, OrderedHashSet::NumberOfElementsOffset()))); - Node* const number_of_deleted = SmiUntag(CAST(LoadObjectField( + TNode<IntPtrT> const number_of_deleted = SmiUntag(CAST(LoadObjectField( table, OrderedHashSet::NumberOfDeletedElementsOffset()))); occupancy.Bind(IntPtrAdd(number_of_elements, number_of_deleted)); GotoIf(IntPtrLessThan(occupancy.value(), capacity), &store_new_entry); @@ -1727,9 +1763,9 @@ TF_BUILTIN(SetPrototypeAdd, CollectionsBuiltinsAssembler) { table_var = CAST(LoadObjectField(receiver, JSMap::kTableOffset)); number_of_buckets.Bind(SmiUntag(CAST(UnsafeLoadFixedArrayElement( table_var.value(), OrderedHashSet::NumberOfBucketsIndex())))); - Node* const new_number_of_elements = SmiUntag(CAST(LoadObjectField( + TNode<IntPtrT> const new_number_of_elements = SmiUntag(CAST(LoadObjectField( table_var.value(), OrderedHashSet::NumberOfElementsOffset()))); - Node* const new_number_of_deleted = SmiUntag(CAST(LoadObjectField( + TNode<IntPtrT> const new_number_of_deleted = SmiUntag(CAST(LoadObjectField( table_var.value(), OrderedHashSet::NumberOfDeletedElementsOffset()))); occupancy.Bind(IntPtrAdd(new_number_of_elements, new_number_of_deleted)); Goto(&store_new_entry); @@ -1745,13 +1781,13 @@ TF_BUILTIN(SetPrototypeAdd, CollectionsBuiltinsAssembler) { void CollectionsBuiltinsAssembler::StoreOrderedHashSetNewEntry( TNode<OrderedHashSet> const table, Node* const key, Node* const hash, Node* const number_of_buckets, Node* const occupancy) { - Node* const bucket = + TNode<WordT> const bucket = WordAnd(hash, IntPtrSub(number_of_buckets, IntPtrConstant(1))); TNode<Smi> bucket_entry = CAST(UnsafeLoadFixedArrayElement( table, bucket, OrderedHashSet::HashTableStartIndex() * kTaggedSize)); // Store the entry elements. - Node* const entry_start = IntPtrAdd( + TNode<WordT> const entry_start = IntPtrAdd( IntPtrMul(occupancy, IntPtrConstant(OrderedHashSet::kEntrySize)), number_of_buckets); UnsafeStoreFixedArrayElement( @@ -1846,7 +1882,8 @@ TF_BUILTIN(MapPrototypeGetSize, CollectionsBuiltinsAssembler) { Node* const context = Parameter(Descriptor::kContext); ThrowIfNotInstanceType(context, receiver, JS_MAP_TYPE, "get Map.prototype.size"); - Node* const table = LoadObjectField(receiver, JSMap::kTableOffset); + TNode<OrderedHashMap> const table = + CAST(LoadObjectField(receiver, JSMap::kTableOffset)); Return(LoadObjectField(table, OrderedHashMap::NumberOfElementsOffset())); } @@ -1855,20 +1892,20 @@ TF_BUILTIN(MapPrototypeForEach, CollectionsBuiltinsAssembler) { Node* const argc = Parameter(Descriptor::kJSActualArgumentsCount); Node* const context = Parameter(Descriptor::kContext); CodeStubArguments args(this, ChangeInt32ToIntPtr(argc)); - Node* const receiver = args.GetReceiver(); - Node* const callback = args.GetOptionalArgumentValue(0); - Node* const this_arg = args.GetOptionalArgumentValue(1); + TNode<Object> const receiver = args.GetReceiver(); + TNode<Object> const callback = args.GetOptionalArgumentValue(0); + TNode<Object> const this_arg = args.GetOptionalArgumentValue(1); ThrowIfNotInstanceType(context, receiver, JS_MAP_TYPE, kMethodName); // Ensure that {callback} is actually callable. Label callback_not_callable(this, Label::kDeferred); GotoIf(TaggedIsSmi(callback), &callback_not_callable); - GotoIfNot(IsCallable(callback), &callback_not_callable); + GotoIfNot(IsCallable(CAST(callback)), &callback_not_callable); TVARIABLE(IntPtrT, var_index, IntPtrConstant(0)); TVARIABLE(OrderedHashMap, var_table, - CAST(LoadObjectField(receiver, JSMap::kTableOffset))); + CAST(LoadObjectField(CAST(receiver), JSMap::kTableOffset))); Label loop(this, {&var_index, &var_table}), done_loop(this); Goto(&loop); BIND(&loop); @@ -1887,7 +1924,7 @@ TF_BUILTIN(MapPrototypeForEach, CollectionsBuiltinsAssembler) { NextSkipHoles<OrderedHashMap>(table, index, &done_loop); // Load the entry value as well. - Node* entry_value = LoadFixedArrayElement( + TNode<Object> entry_value = LoadFixedArrayElement( table, entry_start_position, (OrderedHashMap::HashTableStartIndex() + OrderedHashMap::kValueOffset) * kTaggedSize); @@ -1938,7 +1975,7 @@ TF_BUILTIN(MapIteratorPrototypeNext, CollectionsBuiltinsAssembler) { // Ensure that the {receiver} is actually a JSMapIterator. Label if_receiver_valid(this), if_receiver_invalid(this, Label::kDeferred); GotoIf(TaggedIsSmi(receiver), &if_receiver_invalid); - Node* const receiver_instance_type = LoadInstanceType(receiver); + TNode<Uint16T> const receiver_instance_type = LoadInstanceType(receiver); GotoIf( InstanceTypeEqual(receiver_instance_type, JS_MAP_KEY_VALUE_ITERATOR_TYPE), &if_receiver_valid); @@ -1992,7 +2029,7 @@ TF_BUILTIN(MapIteratorPrototypeNext, CollectionsBuiltinsAssembler) { BIND(&return_value); { - Node* result = + TNode<JSObject> result = AllocateJSIteratorResult(context, var_value.value(), var_done.value()); Return(result); } @@ -2012,7 +2049,7 @@ TF_BUILTIN(SetPrototypeHas, CollectionsBuiltinsAssembler) { ThrowIfNotInstanceType(context, receiver, JS_SET_TYPE, "Set.prototype.has"); - Node* const table = LoadObjectField(receiver, JSMap::kTableOffset); + TNode<Object> const table = LoadObjectField(receiver, JSMap::kTableOffset); VARIABLE(entry_start_position, MachineType::PointerRepresentation(), IntPtrConstant(0)); @@ -2022,8 +2059,8 @@ TF_BUILTIN(SetPrototypeHas, CollectionsBuiltinsAssembler) { GotoIf(TaggedIsSmi(key), &if_key_smi); - Node* key_map = LoadMap(key); - Node* key_instance_type = LoadMapInstanceType(key_map); + TNode<Map> key_map = LoadMap(key); + TNode<Uint16T> key_instance_type = LoadMapInstanceType(key_map); GotoIf(IsStringInstanceType(key_instance_type), &if_key_string); GotoIf(IsHeapNumberMap(key_map), &if_key_heap_number); @@ -2077,7 +2114,8 @@ TF_BUILTIN(SetPrototypeGetSize, CollectionsBuiltinsAssembler) { Node* const context = Parameter(Descriptor::kContext); ThrowIfNotInstanceType(context, receiver, JS_SET_TYPE, "get Set.prototype.size"); - Node* const table = LoadObjectField(receiver, JSSet::kTableOffset); + TNode<OrderedHashSet> const table = + CAST(LoadObjectField(receiver, JSSet::kTableOffset)); Return(LoadObjectField(table, OrderedHashSet::NumberOfElementsOffset())); } @@ -2086,20 +2124,20 @@ TF_BUILTIN(SetPrototypeForEach, CollectionsBuiltinsAssembler) { Node* const argc = Parameter(Descriptor::kJSActualArgumentsCount); Node* const context = Parameter(Descriptor::kContext); CodeStubArguments args(this, ChangeInt32ToIntPtr(argc)); - Node* const receiver = args.GetReceiver(); - Node* const callback = args.GetOptionalArgumentValue(0); - Node* const this_arg = args.GetOptionalArgumentValue(1); + TNode<Object> const receiver = args.GetReceiver(); + TNode<Object> const callback = args.GetOptionalArgumentValue(0); + TNode<Object> const this_arg = args.GetOptionalArgumentValue(1); ThrowIfNotInstanceType(context, receiver, JS_SET_TYPE, kMethodName); // Ensure that {callback} is actually callable. Label callback_not_callable(this, Label::kDeferred); GotoIf(TaggedIsSmi(callback), &callback_not_callable); - GotoIfNot(IsCallable(callback), &callback_not_callable); + GotoIfNot(IsCallable(CAST(callback)), &callback_not_callable); TVARIABLE(IntPtrT, var_index, IntPtrConstant(0)); TVARIABLE(OrderedHashSet, var_table, - CAST(LoadObjectField(receiver, JSSet::kTableOffset))); + CAST(LoadObjectField(CAST(receiver), JSSet::kTableOffset))); Label loop(this, {&var_index, &var_table}), done_loop(this); Goto(&loop); BIND(&loop); @@ -2154,7 +2192,7 @@ TF_BUILTIN(SetIteratorPrototypeNext, CollectionsBuiltinsAssembler) { // Ensure that the {receiver} is actually a JSSetIterator. Label if_receiver_valid(this), if_receiver_invalid(this, Label::kDeferred); GotoIf(TaggedIsSmi(receiver), &if_receiver_invalid); - Node* const receiver_instance_type = LoadInstanceType(receiver); + TNode<Uint16T> const receiver_instance_type = LoadInstanceType(receiver); GotoIf(InstanceTypeEqual(receiver_instance_type, JS_SET_VALUE_ITERATOR_TYPE), &if_receiver_valid); Branch( @@ -2200,7 +2238,7 @@ TF_BUILTIN(SetIteratorPrototypeNext, CollectionsBuiltinsAssembler) { BIND(&return_value); { - Node* result = + TNode<JSObject> result = AllocateJSIteratorResult(context, var_value.value(), var_done.value()); Return(result); } @@ -2222,8 +2260,8 @@ void CollectionsBuiltinsAssembler::TryLookupOrderedHashTableIndex( GotoIf(TaggedIsSmi(key), &if_key_smi); - Node* key_map = LoadMap(key); - Node* key_instance_type = LoadMapInstanceType(key_map); + TNode<Map> key_map = LoadMap(key); + TNode<Uint16T> key_instance_type = LoadMapInstanceType(key_map); GotoIf(IsStringInstanceType(key_instance_type), &if_key_string); GotoIf(IsHeapNumberMap(key_map), &if_key_heap_number); @@ -2449,7 +2487,7 @@ TNode<IntPtrT> WeakCollectionsBuiltinsAssembler::FindKeyIndexForKey( auto match_key_or_exit_on_empty = [&](TNode<Object> entry_key, Label* if_same) { GotoIf(IsUndefined(entry_key), if_not_found); - GotoIf(WordEqual(entry_key, key), if_same); + GotoIf(TaggedEqual(entry_key, key), if_same); }; return FindKeyIndex(table, hash, entry_mask, match_key_or_exit_on_empty); } @@ -2606,7 +2644,7 @@ TF_BUILTIN(WeakMapGet, WeakCollectionsBuiltinsAssembler) { TNode<Smi> const index = CAST(CallBuiltin(Builtins::kWeakMapLookupHashIndex, context, table, key)); - GotoIf(WordEqual(index, SmiConstant(-1)), &return_undefined); + GotoIf(TaggedEqual(index, SmiConstant(-1)), &return_undefined); Return(LoadFixedArrayElement(table, SmiUntag(index))); @@ -2625,10 +2663,10 @@ TF_BUILTIN(WeakMapPrototypeHas, WeakCollectionsBuiltinsAssembler) { "WeakMap.prototype.has"); TNode<EphemeronHashTable> const table = LoadTable(CAST(receiver)); - Node* const index = + TNode<Object> const index = CallBuiltin(Builtins::kWeakMapLookupHashIndex, context, table, key); - GotoIf(WordEqual(index, SmiConstant(-1)), &return_false); + GotoIf(TaggedEqual(index, SmiConstant(-1)), &return_false); Return(TrueConstant()); @@ -2788,11 +2826,11 @@ TF_BUILTIN(WeakSetPrototypeHas, WeakCollectionsBuiltinsAssembler) { ThrowIfNotInstanceType(context, receiver, JS_WEAK_SET_TYPE, "WeakSet.prototype.has"); - Node* const table = LoadTable(CAST(receiver)); - Node* const index = + TNode<EphemeronHashTable> const table = LoadTable(CAST(receiver)); + TNode<Object> const index = CallBuiltin(Builtins::kWeakMapLookupHashIndex, context, table, key); - GotoIf(WordEqual(index, SmiConstant(-1)), &return_false); + GotoIf(TaggedEqual(index, SmiConstant(-1)), &return_false); Return(TrueConstant()); diff --git a/deps/v8/src/builtins/builtins-console-gen.cc b/deps/v8/src/builtins/builtins-console-gen.cc index 8dc7e5e8f6..1d6a22f611 100644 --- a/deps/v8/src/builtins/builtins-console-gen.cc +++ b/deps/v8/src/builtins/builtins-console-gen.cc @@ -17,7 +17,8 @@ TF_BUILTIN(FastConsoleAssert, CodeStubAssembler) { // TODO(ishell): use constants from Descriptor once the JSFunction linkage // arguments are reordered. - Node* argc = Parameter(Descriptor::kJSActualArgumentsCount); + TNode<Int32T> argc = + UncheckedCast<Int32T>(Parameter(Descriptor::kJSActualArgumentsCount)); Node* context = Parameter(Descriptor::kContext); Node* new_target = Parameter(Descriptor::kJSNewTarget); GotoIf(Word32Equal(argc, Int32Constant(0)), &runtime); diff --git a/deps/v8/src/builtins/builtins-constructor-gen.cc b/deps/v8/src/builtins/builtins-constructor-gen.cc index 767e626432..856718cedf 100644 --- a/deps/v8/src/builtins/builtins-constructor-gen.cc +++ b/deps/v8/src/builtins/builtins-constructor-gen.cc @@ -68,7 +68,7 @@ TF_BUILTIN(FastNewClosure, ConstructorBuiltinsAssembler) { // Bump the closure counter encoded the {feedback_cell}s map. { - Node* const feedback_cell_map = LoadMap(feedback_cell); + TNode<Map> const feedback_cell_map = LoadMap(feedback_cell); Label no_closures(this), one_closure(this), cell_done(this); GotoIf(IsNoClosuresCellMap(feedback_cell_map), &no_closures); @@ -93,23 +93,23 @@ TF_BUILTIN(FastNewClosure, ConstructorBuiltinsAssembler) { Node* const flags = LoadObjectField(shared_function_info, SharedFunctionInfo::kFlagsOffset, MachineType::Uint32()); - Node* const function_map_index = IntPtrAdd( + TNode<IntPtrT> const function_map_index = Signed(IntPtrAdd( DecodeWordFromWord32<SharedFunctionInfo::FunctionMapIndexBits>(flags), - IntPtrConstant(Context::FIRST_FUNCTION_MAP_INDEX)); + IntPtrConstant(Context::FIRST_FUNCTION_MAP_INDEX))); CSA_ASSERT(this, UintPtrLessThanOrEqual( function_map_index, IntPtrConstant(Context::LAST_FUNCTION_MAP_INDEX))); // Get the function map in the current native context and set that // as the map of the allocated object. - Node* const native_context = LoadNativeContext(context); - Node* const function_map = - LoadContextElement(native_context, function_map_index); + TNode<NativeContext> const native_context = LoadNativeContext(context); + TNode<Map> const function_map = + CAST(LoadContextElement(native_context, function_map_index)); // Create a new closure from the given function info in new space TNode<IntPtrT> instance_size_in_bytes = TimesTaggedSize(LoadMapInstanceSizeInWords(function_map)); - TNode<Object> result = Allocate(instance_size_in_bytes); + TNode<HeapObject> result = Allocate(instance_size_in_bytes); StoreMapNoWriteBarrier(result, function_map); InitializeJSObjectBodyNoSlackTracking(result, function_map, instance_size_in_bytes, @@ -141,7 +141,7 @@ TF_BUILTIN(FastNewClosure, ConstructorBuiltinsAssembler) { StoreObjectFieldNoWriteBarrier(result, JSFunction::kContextOffset, context); Handle<Code> lazy_builtin_handle = isolate()->builtins()->builtin_handle(Builtins::kCompileLazy); - Node* lazy_builtin = HeapConstant(lazy_builtin_handle); + TNode<Code> lazy_builtin = HeapConstant(lazy_builtin_handle); StoreObjectFieldNoWriteBarrier(result, JSFunction::kCodeOffset, lazy_builtin); Return(result); } @@ -189,16 +189,18 @@ compiler::TNode<JSObject> ConstructorBuiltinsAssembler::EmitFastNewObject( BIND(&fast); // Load the initial map and verify that it's in fact a map. - Node* initial_map = + TNode<Object> initial_map_or_proto = LoadObjectField(new_target, JSFunction::kPrototypeOrInitialMapOffset); - GotoIf(TaggedIsSmi(initial_map), call_runtime); - GotoIf(DoesntHaveInstanceType(initial_map, MAP_TYPE), call_runtime); + GotoIf(TaggedIsSmi(initial_map_or_proto), call_runtime); + GotoIf(DoesntHaveInstanceType(CAST(initial_map_or_proto), MAP_TYPE), + call_runtime); + TNode<Map> initial_map = CAST(initial_map_or_proto); // Fall back to runtime if the target differs from the new target's // initial map constructor. - Node* new_target_constructor = + TNode<Object> new_target_constructor = LoadObjectField(initial_map, Map::kConstructorOrBackPointerOffset); - GotoIf(WordNotEqual(target, new_target_constructor), call_runtime); + GotoIf(TaggedNotEqual(target, new_target_constructor), call_runtime); VARIABLE(properties, MachineRepresentation::kTagged); @@ -253,12 +255,12 @@ Node* ConstructorBuiltinsAssembler::EmitFastNewFunctionContext( context); StoreObjectFieldNoWriteBarrier(function_context, Context::kExtensionOffset, TheHoleConstant()); - TNode<Context> native_context = LoadNativeContext(context); + TNode<NativeContext> native_context = LoadNativeContext(context); StoreObjectFieldNoWriteBarrier(function_context, Context::kNativeContextOffset, native_context); // Initialize the varrest of the slots to undefined. - TNode<HeapObject> undefined = UndefinedConstant(); + TNode<Oddball> undefined = UndefinedConstant(); TNode<IntPtrT> start_offset = IntPtrConstant(Context::kTodoHeaderSize); CodeStubAssembler::VariableList vars(0, zone()); BuildFastLoop( @@ -302,9 +304,9 @@ Node* ConstructorBuiltinsAssembler::EmitCreateRegExpLiteral( Node* boilerplate = literal_site; CSA_ASSERT(this, IsJSRegExp(boilerplate)); int size = JSRegExp::kSize + JSRegExp::kInObjectFieldCount * kTaggedSize; - Node* copy = Allocate(size); + TNode<HeapObject> copy = Allocate(size); for (int offset = 0; offset < size; offset += kTaggedSize) { - Node* value = LoadObjectField(boilerplate, offset); + TNode<Object> value = LoadObjectField(boilerplate, offset); StoreObjectFieldNoWriteBarrier(copy, offset, value); } result.Bind(copy); @@ -324,7 +326,7 @@ Node* ConstructorBuiltinsAssembler::EmitCreateRegExpLiteral( TF_BUILTIN(CreateRegExpLiteral, ConstructorBuiltinsAssembler) { Node* feedback_vector = Parameter(Descriptor::kFeedbackVector); - Node* slot = SmiUntag(Parameter(Descriptor::kSlot)); + TNode<IntPtrT> slot = SmiUntag(Parameter(Descriptor::kSlot)); Node* pattern = Parameter(Descriptor::kPattern); Node* flags = Parameter(Descriptor::kFlags); Node* context = Parameter(Descriptor::kContext); @@ -357,7 +359,7 @@ Node* ConstructorBuiltinsAssembler::EmitCreateShallowArrayLiteral( TF_BUILTIN(CreateShallowArrayLiteral, ConstructorBuiltinsAssembler) { Node* feedback_vector = Parameter(Descriptor::kFeedbackVector); - Node* slot = SmiUntag(Parameter(Descriptor::kSlot)); + TNode<IntPtrT> slot = SmiUntag(Parameter(Descriptor::kSlot)); Node* constant_elements = Parameter(Descriptor::kConstantElements); Node* context = Parameter(Descriptor::kContext); Label call_runtime(this, Label::kDeferred); @@ -400,7 +402,7 @@ Node* ConstructorBuiltinsAssembler::EmitCreateEmptyArrayLiteral( BIND(&create_empty_array); TNode<Int32T> kind = LoadElementsKind(allocation_site.value()); - TNode<Context> native_context = LoadNativeContext(context); + TNode<NativeContext> native_context = LoadNativeContext(context); Comment("LoadJSArrayElementsMap"); TNode<Map> array_map = LoadJSArrayElementsMap(kind, native_context); TNode<Smi> zero = SmiConstant(0); @@ -417,7 +419,7 @@ Node* ConstructorBuiltinsAssembler::EmitCreateEmptyArrayLiteral( TF_BUILTIN(CreateEmptyArrayLiteral, ConstructorBuiltinsAssembler) { Node* feedback_vector = Parameter(Descriptor::kFeedbackVector); - Node* slot = SmiUntag(Parameter(Descriptor::kSlot)); + TNode<IntPtrT> slot = SmiUntag(Parameter(Descriptor::kSlot)); Node* context = Parameter(Descriptor::kContext); Node* result = EmitCreateEmptyArrayLiteral(feedback_vector, slot, context); Return(result); @@ -436,7 +438,7 @@ Node* ConstructorBuiltinsAssembler::EmitCreateShallowObjectLiteral( VARIABLE(var_properties, MachineRepresentation::kTagged); { - Node* bit_field_3 = LoadMapBitField3(boilerplate_map); + TNode<Uint32T> bit_field_3 = LoadMapBitField3(boilerplate_map); GotoIf(IsSetWord32<Map::IsDeprecatedBit>(bit_field_3), call_runtime); // Directly copy over the property store for dict-mode boilerplates. Label if_dictionary(this), if_fast(this), done(this); @@ -453,7 +455,8 @@ Node* ConstructorBuiltinsAssembler::EmitCreateShallowObjectLiteral( BIND(&if_fast); { // TODO(cbruni): support copying out-of-object properties. - Node* boilerplate_properties = LoadFastProperties(boilerplate); + TNode<HeapObject> boilerplate_properties = + LoadFastProperties(boilerplate); GotoIfNot(IsEmptyFixedArray(boilerplate_properties), call_runtime); var_properties.Bind(EmptyFixedArrayConstant()); Goto(&done); @@ -465,7 +468,7 @@ Node* ConstructorBuiltinsAssembler::EmitCreateShallowObjectLiteral( { // Copy the elements backing store, assuming that it's flat. Label if_empty_fixed_array(this), if_copy_elements(this), done(this); - Node* boilerplate_elements = LoadElements(boilerplate); + TNode<FixedArrayBase> boilerplate_elements = LoadElements(boilerplate); Branch(IsEmptyFixedArray(boilerplate_elements), &if_empty_fixed_array, &if_copy_elements); @@ -520,26 +523,28 @@ Node* ConstructorBuiltinsAssembler::EmitCreateShallowObjectLiteral( // Copy over in-object properties. Label continue_with_write_barrier(this), done_init(this); TVARIABLE(IntPtrT, offset, IntPtrConstant(JSObject::kHeaderSize)); - // Mutable heap numbers only occur on 32-bit platforms. + // Heap numbers are only mutable on 32-bit platforms. bool may_use_mutable_heap_numbers = !FLAG_unbox_double_fields; { Comment("Copy in-object properties fast"); Label continue_fast(this, &offset); - Branch(WordEqual(offset.value(), instance_size), &done_init, + Branch(IntPtrEqual(offset.value(), instance_size), &done_init, &continue_fast); BIND(&continue_fast); if (may_use_mutable_heap_numbers) { TNode<Object> field = LoadObjectField(boilerplate, offset.value()); Label store_field(this); GotoIf(TaggedIsSmi(field), &store_field); - GotoIf(IsMutableHeapNumber(CAST(field)), &continue_with_write_barrier); + // TODO(leszeks): Read the field descriptor to decide if this heap + // number is mutable or not. + GotoIf(IsHeapNumber(CAST(field)), &continue_with_write_barrier); Goto(&store_field); BIND(&store_field); StoreObjectFieldNoWriteBarrier(copy, offset.value(), field); } else { // Copy fields as raw data. - TNode<IntPtrT> field = - LoadObjectField<IntPtrT>(boilerplate, offset.value()); + TNode<TaggedT> field = + LoadObjectField<TaggedT>(boilerplate, offset.value()); StoreObjectFieldNoWriteBarrier(copy, offset.value(), field); } offset = IntPtrAdd(offset.value(), IntPtrConstant(kTaggedSize)); @@ -562,7 +567,7 @@ Node* ConstructorBuiltinsAssembler::EmitCreateShallowObjectLiteral( offset.value(), instance_size, [=](Node* offset) { // TODO(ishell): value decompression is not necessary here. - Node* field = LoadObjectField(boilerplate, offset); + TNode<Object> field = LoadObjectField(boilerplate, offset); StoreObjectFieldNoWriteBarrier(copy, offset, field); }, kTaggedSize, INTPTR_PARAMETERS, IndexAdvanceMode::kPost); @@ -570,19 +575,20 @@ Node* ConstructorBuiltinsAssembler::EmitCreateShallowObjectLiteral( BuildFastLoop( offset.value(), instance_size, [=](Node* offset) { - Node* field = LoadObjectField(copy, offset); - Label copy_mutable_heap_number(this, Label::kDeferred), - continue_loop(this); + TNode<Object> field = LoadObjectField(copy, offset); + Label copy_heap_number(this, Label::kDeferred), continue_loop(this); // We only have to clone complex field values. GotoIf(TaggedIsSmi(field), &continue_loop); - Branch(IsMutableHeapNumber(field), ©_mutable_heap_number, + // TODO(leszeks): Read the field descriptor to decide if this heap + // number is mutable or not. + Branch(IsHeapNumber(CAST(field)), ©_heap_number, &continue_loop); - BIND(©_mutable_heap_number); + BIND(©_heap_number); { - Node* double_value = LoadHeapNumberValue(field); - Node* mutable_heap_number = - AllocateMutableHeapNumberWithValue(double_value); - StoreObjectField(copy, offset, mutable_heap_number); + TNode<Float64T> double_value = LoadHeapNumberValue(CAST(field)); + TNode<HeapNumber> heap_number = + AllocateHeapNumberWithValue(double_value); + StoreObjectField(copy, offset, heap_number); Goto(&continue_loop); } BIND(&continue_loop); @@ -598,7 +604,7 @@ Node* ConstructorBuiltinsAssembler::EmitCreateShallowObjectLiteral( TF_BUILTIN(CreateShallowObjectLiteral, ConstructorBuiltinsAssembler) { Label call_runtime(this); Node* feedback_vector = Parameter(Descriptor::kFeedbackVector); - Node* slot = SmiUntag(Parameter(Descriptor::kSlot)); + TNode<IntPtrT> slot = SmiUntag(Parameter(Descriptor::kSlot)); Node* copy = EmitCreateShallowObjectLiteral(feedback_vector, slot, &call_runtime); Return(copy); @@ -615,18 +621,17 @@ TF_BUILTIN(CreateShallowObjectLiteral, ConstructorBuiltinsAssembler) { // Used by the CreateEmptyObjectLiteral bytecode and the Object constructor. Node* ConstructorBuiltinsAssembler::EmitCreateEmptyObjectLiteral( Node* context) { - Node* native_context = LoadNativeContext(context); - Node* object_function = - LoadContextElement(native_context, Context::OBJECT_FUNCTION_INDEX); - Node* map = LoadObjectField(object_function, - JSFunction::kPrototypeOrInitialMapOffset); - CSA_ASSERT(this, IsMap(map)); + TNode<NativeContext> native_context = LoadNativeContext(context); + TNode<JSFunction> object_function = + CAST(LoadContextElement(native_context, Context::OBJECT_FUNCTION_INDEX)); + TNode<Map> map = CAST(LoadObjectField( + object_function, JSFunction::kPrototypeOrInitialMapOffset)); // Ensure that slack tracking is disabled for the map. STATIC_ASSERT(Map::kNoSlackTracking == 0); CSA_ASSERT( this, IsClearWord32<Map::ConstructionCounterBits>(LoadMapBitField3(map))); - Node* empty_fixed_array = EmptyFixedArrayConstant(); - Node* result = + TNode<FixedArray> empty_fixed_array = EmptyFixedArrayConstant(); + TNode<JSObject> result = AllocateJSObjectFromMap(map, empty_fixed_array, empty_fixed_array); return result; } @@ -634,22 +639,22 @@ Node* ConstructorBuiltinsAssembler::EmitCreateEmptyObjectLiteral( // ES #sec-object-constructor TF_BUILTIN(ObjectConstructor, ConstructorBuiltinsAssembler) { int const kValueArg = 0; - Node* argc = + TNode<IntPtrT> argc = ChangeInt32ToIntPtr(Parameter(Descriptor::kJSActualArgumentsCount)); CodeStubArguments args(this, argc); Node* context = Parameter(Descriptor::kContext); - Node* new_target = Parameter(Descriptor::kJSNewTarget); + TNode<Object> new_target = CAST(Parameter(Descriptor::kJSNewTarget)); VARIABLE(var_result, MachineRepresentation::kTagged); Label if_subclass(this, Label::kDeferred), if_notsubclass(this), return_result(this); GotoIf(IsUndefined(new_target), &if_notsubclass); TNode<JSFunction> target = CAST(Parameter(Descriptor::kJSTarget)); - Branch(WordEqual(new_target, target), &if_notsubclass, &if_subclass); + Branch(TaggedEqual(new_target, target), &if_notsubclass, &if_subclass); BIND(&if_subclass); { - Node* result = + TNode<Object> result = CallBuiltin(Builtins::kFastNewObject, context, target, new_target); var_result.Bind(result); Goto(&return_result); @@ -659,9 +664,9 @@ TF_BUILTIN(ObjectConstructor, ConstructorBuiltinsAssembler) { { Label if_newobject(this, Label::kDeferred), if_toobject(this); - Node* value_index = IntPtrConstant(kValueArg); + TNode<IntPtrT> value_index = IntPtrConstant(kValueArg); GotoIf(UintPtrGreaterThanOrEqual(value_index, argc), &if_newobject); - Node* value = args.AtIndex(value_index); + TNode<Object> value = args.AtIndex(value_index); GotoIf(IsNull(value), &if_newobject); Branch(IsUndefined(value), &if_newobject, &if_toobject); @@ -674,7 +679,7 @@ TF_BUILTIN(ObjectConstructor, ConstructorBuiltinsAssembler) { BIND(&if_toobject); { - Node* result = CallBuiltin(Builtins::kToObject, context, value); + TNode<Object> result = CallBuiltin(Builtins::kToObject, context, value); var_result.Bind(result); Goto(&return_result); } @@ -687,20 +692,20 @@ TF_BUILTIN(ObjectConstructor, ConstructorBuiltinsAssembler) { // ES #sec-number-constructor TF_BUILTIN(NumberConstructor, ConstructorBuiltinsAssembler) { Node* context = Parameter(Descriptor::kContext); - Node* argc = + TNode<IntPtrT> argc = ChangeInt32ToIntPtr(Parameter(Descriptor::kJSActualArgumentsCount)); CodeStubArguments args(this, argc); // 1. If no arguments were passed to this function invocation, let n be +0. VARIABLE(var_n, MachineRepresentation::kTagged, SmiConstant(0)); Label if_nloaded(this, &var_n); - GotoIf(WordEqual(argc, IntPtrConstant(0)), &if_nloaded); + GotoIf(IntPtrEqual(argc, IntPtrConstant(0)), &if_nloaded); // 2. Else, // a. Let prim be ? ToNumeric(value). // b. If Type(prim) is BigInt, let n be the Number value for prim. // c. Otherwise, let n be prim. - Node* value = args.AtIndex(0); + TNode<Object> value = args.AtIndex(0); var_n.Bind(ToNumber(context, value, BigIntHandling::kConvertToNumber)); Goto(&if_nloaded); @@ -726,7 +731,7 @@ TF_BUILTIN(NumberConstructor, ConstructorBuiltinsAssembler) { // from the current frame here in order to reduce register pressure on the // fast path. TNode<JSFunction> target = LoadTargetFromFrame(); - Node* result = + TNode<Object> result = CallBuiltin(Builtins::kFastNewObject, context, target, new_target); StoreObjectField(result, JSPrimitiveWrapper::kValueOffset, n_value); args.PopAndReturn(result); @@ -739,66 +744,5 @@ TF_BUILTIN(GenericLazyDeoptContinuation, ConstructorBuiltinsAssembler) { Return(result); } -// https://tc39.github.io/ecma262/#sec-string-constructor -TF_BUILTIN(StringConstructor, ConstructorBuiltinsAssembler) { - Node* context = Parameter(Descriptor::kContext); - Node* argc = - ChangeInt32ToIntPtr(Parameter(Descriptor::kJSActualArgumentsCount)); - CodeStubArguments args(this, argc); - - TNode<Object> new_target = CAST(Parameter(Descriptor::kJSNewTarget)); - - // 1. If no arguments were passed to this function invocation, let s be "". - VARIABLE(var_s, MachineRepresentation::kTagged, EmptyStringConstant()); - Label if_sloaded(this, &var_s); - GotoIf(WordEqual(argc, IntPtrConstant(0)), &if_sloaded); - - // 2. Else, - // a. If NewTarget is undefined [...] - Node* value = args.AtIndex(0); - Label if_tostring(this, &var_s); - GotoIfNot(IsUndefined(new_target), &if_tostring); - - // 2a. [...] and Type(value) is Symbol, return SymbolDescriptiveString(value). - GotoIf(TaggedIsSmi(value), &if_tostring); - GotoIfNot(IsSymbol(value), &if_tostring); - { - Node* result = - CallRuntime(Runtime::kSymbolDescriptiveString, context, value); - args.PopAndReturn(result); - } - - // 2b. Let s be ? ToString(value). - BIND(&if_tostring); - { - var_s.Bind(CallBuiltin(Builtins::kToString, context, value)); - Goto(&if_sloaded); - } - - // 3. If NewTarget is undefined, return s. - BIND(&if_sloaded); - { - Node* s_value = var_s.value(); - Label return_s(this), constructstring(this, Label::kDeferred); - Branch(IsUndefined(new_target), &return_s, &constructstring); - - BIND(&return_s); - { args.PopAndReturn(s_value); } - - BIND(&constructstring); - { - // 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(); - - Node* result = - CallBuiltin(Builtins::kFastNewObject, context, target, new_target); - StoreObjectField(result, JSPrimitiveWrapper::kValueOffset, s_value); - args.PopAndReturn(result); - } - } -} - } // namespace internal } // namespace v8 diff --git a/deps/v8/src/builtins/builtins-conversion-gen.cc b/deps/v8/src/builtins/builtins-conversion-gen.cc index 71a9cbf145..8a0c73b292 100644 --- a/deps/v8/src/builtins/builtins-conversion-gen.cc +++ b/deps/v8/src/builtins/builtins-conversion-gen.cc @@ -29,7 +29,7 @@ class ConversionBuiltinsAssembler : public CodeStubAssembler { void ConversionBuiltinsAssembler::Generate_NonPrimitiveToPrimitive( Node* context, Node* input, ToPrimitiveHint hint) { // Lookup the @@toPrimitive property on the {input}. - Node* exotic_to_prim = + TNode<Object> exotic_to_prim = GetProperty(context, input, factory()->to_primitive_symbol()); // Check if {exotic_to_prim} is neither null nor undefined. @@ -40,7 +40,8 @@ void ConversionBuiltinsAssembler::Generate_NonPrimitiveToPrimitive( // representation of the {hint}. Callable callable = CodeFactory::Call(isolate(), ConvertReceiverMode::kNotNullOrUndefined); - Node* hint_string = HeapConstant(factory()->ToPrimitiveHintString(hint)); + TNode<String> hint_string = + HeapConstant(factory()->ToPrimitiveHintString(hint)); Node* result = CallJS(callable, context, exotic_to_prim, input, hint_string); @@ -48,7 +49,7 @@ void ConversionBuiltinsAssembler::Generate_NonPrimitiveToPrimitive( Label if_resultisprimitive(this), if_resultisnotprimitive(this, Label::kDeferred); GotoIf(TaggedIsSmi(result), &if_resultisprimitive); - Node* result_instance_type = LoadInstanceType(result); + TNode<Uint16T> result_instance_type = LoadInstanceType(result); Branch(IsPrimitiveInstanceType(result_instance_type), &if_resultisprimitive, &if_resultisnotprimitive); @@ -119,7 +120,7 @@ TF_BUILTIN(ToName, CodeStubAssembler) { Label if_inputisbigint(this), if_inputisname(this), if_inputisnumber(this), if_inputisoddball(this), if_inputisreceiver(this, Label::kDeferred); GotoIf(TaggedIsSmi(input), &if_inputisnumber); - Node* input_instance_type = LoadInstanceType(input); + TNode<Uint16T> input_instance_type = LoadInstanceType(input); STATIC_ASSERT(FIRST_NAME_TYPE == FIRST_TYPE); GotoIf(IsNameInstanceType(input_instance_type), &if_inputisname); GotoIf(IsJSReceiverInstanceType(input_instance_type), &if_inputisreceiver); @@ -230,13 +231,13 @@ void ConversionBuiltinsAssembler::Generate_OrdinaryToPrimitive( } for (Handle<String> name : method_names) { // Lookup the {name} on the {input}. - Node* method = GetProperty(context, input, name); + TNode<Object> method = GetProperty(context, input, name); // Check if the {method} is callable. Label if_methodiscallable(this), if_methodisnotcallable(this, Label::kDeferred); GotoIf(TaggedIsSmi(method), &if_methodisnotcallable); - Node* method_map = LoadMap(method); + TNode<Map> method_map = LoadMap(CAST(method)); Branch(IsCallableMap(method_map), &if_methodiscallable, &if_methodisnotcallable); @@ -250,7 +251,7 @@ void ConversionBuiltinsAssembler::Generate_OrdinaryToPrimitive( // Return the {result} if it is a primitive. GotoIf(TaggedIsSmi(result), &return_result); - Node* result_instance_type = LoadInstanceType(result); + TNode<Uint16T> result_instance_type = LoadInstanceType(result); GotoIf(IsPrimitiveInstanceType(result_instance_type), &return_result); } @@ -340,7 +341,7 @@ TF_BUILTIN(ToLength, CodeStubAssembler) { BIND(&if_lenisheapnumber); { // Load the floating-point value of {len}. - Node* len_value = LoadHeapNumberValue(len); + TNode<Float64T> len_value = LoadHeapNumberValue(len); // Check if {len} is not greater than zero. GotoIfNot(Float64GreaterThan(len_value, Float64Constant(0.0)), @@ -352,8 +353,8 @@ TF_BUILTIN(ToLength, CodeStubAssembler) { &return_two53minus1); // Round the {len} towards -Infinity. - Node* value = Float64Floor(len_value); - Node* result = ChangeFloat64ToTagged(value); + TNode<Float64T> value = Float64Floor(len_value); + TNode<Number> result = ChangeFloat64ToTagged(value); Return(result); } @@ -403,11 +404,12 @@ TF_BUILTIN(ToObject, CodeStubAssembler) { GotoIf(TaggedIsSmi(object), &if_smi); - Node* map = LoadMap(object); - Node* instance_type = LoadMapInstanceType(map); + TNode<Map> map = LoadMap(object); + TNode<Uint16T> instance_type = LoadMapInstanceType(map); GotoIf(IsJSReceiverInstanceType(instance_type), &if_jsreceiver); - Node* constructor_function_index = LoadMapConstructorFunctionIndex(map); + TNode<IntPtrT> constructor_function_index = + LoadMapConstructorFunctionIndex(map); GotoIf(WordEqual(constructor_function_index, IntPtrConstant(Map::kNoConstructorFunctionIndex)), &if_noconstructor); @@ -420,12 +422,12 @@ TF_BUILTIN(ToObject, CodeStubAssembler) { Goto(&if_wrapjs_primitive_wrapper); BIND(&if_wrapjs_primitive_wrapper); - TNode<Context> native_context = LoadNativeContext(context); - Node* constructor = LoadContextElement( - native_context, constructor_function_index_var.value()); - Node* initial_map = + TNode<NativeContext> native_context = LoadNativeContext(context); + TNode<JSFunction> constructor = CAST(LoadContextElement( + native_context, constructor_function_index_var.value())); + TNode<Object> initial_map = LoadObjectField(constructor, JSFunction::kPrototypeOrInitialMapOffset); - Node* js_primitive_wrapper = Allocate(JSPrimitiveWrapper::kSize); + TNode<HeapObject> js_primitive_wrapper = Allocate(JSPrimitiveWrapper::kSize); StoreMapNoWriteBarrier(js_primitive_wrapper, initial_map); StoreObjectFieldRoot(js_primitive_wrapper, JSPrimitiveWrapper::kPropertiesOrHashOffset, diff --git a/deps/v8/src/builtins/builtins-date-gen.cc b/deps/v8/src/builtins/builtins-date-gen.cc index ca84948d48..97600efaa4 100644 --- a/deps/v8/src/builtins/builtins-date-gen.cc +++ b/deps/v8/src/builtins/builtins-date-gen.cc @@ -28,7 +28,7 @@ void DateBuiltinsAssembler::Generate_DatePrototype_GetField(Node* context, Label receiver_not_date(this, Label::kDeferred); GotoIf(TaggedIsSmi(receiver), &receiver_not_date); - Node* receiver_instance_type = LoadInstanceType(receiver); + TNode<Uint16T> receiver_instance_type = LoadInstanceType(receiver); GotoIfNot(InstanceTypeEqual(receiver_instance_type, JS_DATE_TYPE), &receiver_not_date); @@ -38,20 +38,20 @@ void DateBuiltinsAssembler::Generate_DatePrototype_GetField(Node* context, } else { if (field_index < JSDate::kFirstUncachedField) { Label stamp_mismatch(this, Label::kDeferred); - Node* date_cache_stamp = Load( - MachineType::AnyTagged(), + TNode<Object> date_cache_stamp = Load<Object>( ExternalConstant(ExternalReference::date_cache_stamp(isolate()))); - Node* cache_stamp = LoadObjectField(receiver, JSDate::kCacheStampOffset); - GotoIf(WordNotEqual(date_cache_stamp, cache_stamp), &stamp_mismatch); + TNode<Object> cache_stamp = + LoadObjectField(receiver, JSDate::kCacheStampOffset); + GotoIf(TaggedNotEqual(date_cache_stamp, cache_stamp), &stamp_mismatch); Return(LoadObjectField(receiver, JSDate::kValueOffset + field_index * kTaggedSize)); BIND(&stamp_mismatch); } - Node* field_index_smi = SmiConstant(field_index); - Node* function = + TNode<Smi> field_index_smi = SmiConstant(field_index); + TNode<ExternalReference> function = ExternalConstant(ExternalReference::get_date_field_function()); Node* result = CallCFunction( function, MachineType::AnyTagged(), @@ -182,7 +182,7 @@ TF_BUILTIN(DatePrototypeValueOf, DateBuiltinsAssembler) { TF_BUILTIN(DatePrototypeToPrimitive, CodeStubAssembler) { Node* context = Parameter(Descriptor::kContext); Node* receiver = Parameter(Descriptor::kReceiver); - Node* hint = Parameter(Descriptor::kHint); + TNode<Object> hint = CAST(Parameter(Descriptor::kHint)); // Check if the {receiver} is actually a JSReceiver. Label receiver_is_invalid(this, Label::kDeferred); @@ -194,25 +194,25 @@ TF_BUILTIN(DatePrototypeToPrimitive, CodeStubAssembler) { hint_is_invalid(this, Label::kDeferred); // Fast cases for internalized strings. - Node* number_string = LoadRoot(RootIndex::knumber_string); - GotoIf(WordEqual(hint, number_string), &hint_is_number); - Node* default_string = LoadRoot(RootIndex::kdefault_string); - GotoIf(WordEqual(hint, default_string), &hint_is_string); - Node* string_string = LoadRoot(RootIndex::kstring_string); - GotoIf(WordEqual(hint, string_string), &hint_is_string); + TNode<String> number_string = numberStringConstant(); + GotoIf(TaggedEqual(hint, number_string), &hint_is_number); + TNode<String> default_string = DefaultStringConstant(); + GotoIf(TaggedEqual(hint, default_string), &hint_is_string); + TNode<String> string_string = StringStringConstant(); + GotoIf(TaggedEqual(hint, string_string), &hint_is_string); // Slow-case with actual string comparisons. GotoIf(TaggedIsSmi(hint), &hint_is_invalid); - GotoIfNot(IsString(hint), &hint_is_invalid); - GotoIf(WordEqual( + GotoIfNot(IsString(CAST(hint)), &hint_is_invalid); + GotoIf(TaggedEqual( CallBuiltin(Builtins::kStringEqual, context, hint, number_string), TrueConstant()), &hint_is_number); - GotoIf(WordEqual( + GotoIf(TaggedEqual( CallBuiltin(Builtins::kStringEqual, context, hint, default_string), TrueConstant()), &hint_is_string); - GotoIf(WordEqual( + GotoIf(TaggedEqual( CallBuiltin(Builtins::kStringEqual, context, hint, string_string), TrueConstant()), &hint_is_string); @@ -223,7 +223,7 @@ TF_BUILTIN(DatePrototypeToPrimitive, CodeStubAssembler) { { Callable callable = CodeFactory::OrdinaryToPrimitive( isolate(), OrdinaryToPrimitiveHint::kNumber); - Node* result = CallStub(callable, context, receiver); + TNode<Object> result = CallStub(callable, context, receiver); Return(result); } @@ -232,7 +232,7 @@ TF_BUILTIN(DatePrototypeToPrimitive, CodeStubAssembler) { { Callable callable = CodeFactory::OrdinaryToPrimitive( isolate(), OrdinaryToPrimitiveHint::kString); - Node* result = CallStub(callable, context, receiver); + TNode<Object> result = CallStub(callable, context, receiver); Return(result); } diff --git a/deps/v8/src/builtins/builtins-date.cc b/deps/v8/src/builtins/builtins-date.cc index d333873542..c3e7601832 100644 --- a/deps/v8/src/builtins/builtins-date.cc +++ b/deps/v8/src/builtins/builtins-date.cc @@ -111,24 +111,23 @@ const char* kShortMonths[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", // ES6 section 20.3.1.16 Date Time String Format double ParseDateTimeString(Isolate* isolate, Handle<String> str) { str = String::Flatten(isolate, str); - // TODO(bmeurer): Change DateParser to not use the FixedArray. - Handle<FixedArray> tmp = - isolate->factory()->NewFixedArray(DateParser::OUTPUT_SIZE); + double out[DateParser::OUTPUT_SIZE]; DisallowHeapAllocation no_gc; String::FlatContent str_content = str->GetFlatContent(no_gc); bool result; if (str_content.IsOneByte()) { - result = DateParser::Parse(isolate, str_content.ToOneByteVector(), *tmp); + result = DateParser::Parse(isolate, str_content.ToOneByteVector(), out); } else { - result = DateParser::Parse(isolate, str_content.ToUC16Vector(), *tmp); + result = DateParser::Parse(isolate, str_content.ToUC16Vector(), out); } if (!result) return std::numeric_limits<double>::quiet_NaN(); - double const day = - MakeDay(tmp->get(0).Number(), tmp->get(1).Number(), tmp->get(2).Number()); - double const time = MakeTime(tmp->get(3).Number(), tmp->get(4).Number(), - tmp->get(5).Number(), tmp->get(6).Number()); + double const day = MakeDay(out[DateParser::YEAR], out[DateParser::MONTH], + out[DateParser::DAY]); + double const time = + MakeTime(out[DateParser::HOUR], out[DateParser::MINUTE], + out[DateParser::SECOND], out[DateParser::MILLISECOND]); double date = MakeDate(day, time); - if (tmp->get(7).IsNull(isolate)) { + if (std::isnan(out[DateParser::UTC_OFFSET])) { if (date >= -DateCache::kMaxTimeBeforeUTCInMs && date <= DateCache::kMaxTimeBeforeUTCInMs) { date = isolate->date_cache()->ToUTC(static_cast<int64_t>(date)); @@ -136,7 +135,7 @@ double ParseDateTimeString(Isolate* isolate, Handle<String> str) { return std::numeric_limits<double>::quiet_NaN(); } } else { - date -= tmp->get(7).Number() * 1000.0; + date -= out[DateParser::UTC_OFFSET] * 1000.0; } return DateCache::TimeClip(date); } diff --git a/deps/v8/src/builtins/builtins-definitions.h b/deps/v8/src/builtins/builtins-definitions.h index 23ab4a88ca..95f5273f14 100644 --- a/deps/v8/src/builtins/builtins-definitions.h +++ b/deps/v8/src/builtins/builtins-definitions.h @@ -207,7 +207,9 @@ namespace internal { TFC(Typeof, Typeof) \ TFC(GetSuperConstructor, Typeof) \ TFC(BigIntToI64, BigIntToI64) \ + TFC(BigIntToI32Pair, BigIntToI32Pair) \ TFC(I64ToBigInt, I64ToBigInt) \ + TFC(I32PairToBigInt, I32PairToBigInt) \ \ /* Type conversions continuations */ \ TFC(ToBooleanLazyDeoptContinuation, TypeConversionStackParameter) \ @@ -222,9 +224,9 @@ namespace internal { TFH(LoadIC_Slow, LoadWithVector) \ TFH(LoadIC_StringLength, LoadWithVector) \ TFH(LoadIC_StringWrapperLength, LoadWithVector) \ - TFH(LoadIC_Uninitialized, LoadWithVector) \ + TFH(LoadIC_NoFeedback, Load) \ TFH(StoreGlobalIC_Slow, StoreWithVector) \ - TFH(StoreIC_Uninitialized, StoreWithVector) \ + TFH(StoreIC_NoFeedback, Store) \ TFH(StoreInArrayLiteralIC_Slow, StoreWithVector) \ TFH(KeyedLoadIC_SloppyArguments, LoadWithVector) \ TFH(LoadIndexedInterceptorIC, LoadWithVector) \ @@ -644,8 +646,6 @@ namespace internal { TFJ(MathCeil, 1, kReceiver, kX) \ /* ES6 #sec-math.floor */ \ TFJ(MathFloor, 1, kReceiver, kX) \ - /* ES6 #sec-math.hypot */ \ - CPP(MathHypot) \ /* ES6 #sec-math.imul */ \ TFJ(MathImul, 2, kReceiver, kX, kY) \ /* ES6 #sec-math.max */ \ @@ -847,32 +847,11 @@ namespace internal { TFJ(RegExpPrototypeCompile, 2, kReceiver, kPattern, kFlags) \ /* ES #sec-regexp.prototype.exec */ \ TFJ(RegExpPrototypeExec, 1, kReceiver, kString) \ - /* ES #sec-get-regexp.prototype.dotAll */ \ - TFJ(RegExpPrototypeDotAllGetter, 0, kReceiver) \ - /* ES #sec-get-regexp.prototype.flags */ \ - TFJ(RegExpPrototypeFlagsGetter, 0, kReceiver) \ - /* ES #sec-get-regexp.prototype.global */ \ - TFJ(RegExpPrototypeGlobalGetter, 0, kReceiver) \ - /* ES #sec-get-regexp.prototype.ignorecase */ \ - TFJ(RegExpPrototypeIgnoreCaseGetter, 0, kReceiver) \ - /* ES #sec-regexp.prototype-@@match */ \ - TFJ(RegExpPrototypeMatch, 1, kReceiver, kString) \ /* https://tc39.github.io/proposal-string-matchall/ */ \ TFJ(RegExpPrototypeMatchAll, 1, kReceiver, kString) \ - /* ES #sec-get-regexp.prototype.multiline */ \ - TFJ(RegExpPrototypeMultilineGetter, 0, kReceiver) \ /* ES #sec-regexp.prototype-@@search */ \ TFJ(RegExpPrototypeSearch, 1, kReceiver, kString) \ - /* ES #sec-get-regexp.prototype.source */ \ - TFJ(RegExpPrototypeSourceGetter, 0, kReceiver) \ - /* ES #sec-get-regexp.prototype.sticky */ \ - TFJ(RegExpPrototypeStickyGetter, 0, kReceiver) \ - /* ES #sec-regexp.prototype.test */ \ - TFJ(RegExpPrototypeTest, 1, kReceiver, kString) \ - TFS(RegExpPrototypeTestFast, kReceiver, kString) \ CPP(RegExpPrototypeToString) \ - /* ES #sec-get-regexp.prototype.unicode */ \ - TFJ(RegExpPrototypeUnicodeGetter, 0, kReceiver) \ CPP(RegExpRightContextGetter) \ \ /* ES #sec-regexp.prototype-@@split */ \ @@ -880,7 +859,7 @@ namespace internal { /* RegExp helpers */ \ TFS(RegExpExecAtom, kRegExp, kString, kLastIndex, kMatchInfo) \ TFS(RegExpExecInternal, kRegExp, kString, kLastIndex, kMatchInfo) \ - TFS(RegExpMatchFast, kReceiver, kPattern) \ + ASM(RegExpInterpreterTrampoline, CCall) \ TFS(RegExpPrototypeExecSlow, kReceiver, kString) \ TFS(RegExpSearchFast, kReceiver, kPattern) \ TFS(RegExpSplit, kRegExp, kString, kLimit) \ @@ -926,8 +905,6 @@ namespace internal { CPP(AtomicsWake) \ \ /* String */ \ - /* ES #sec-string-constructor */ \ - TFJ(StringConstructor, SharedFunctionInfo::kDontAdaptArgumentsSentinel) \ /* ES #sec-string.fromcodepoint */ \ CPP(StringFromCodePoint) \ /* ES6 #sec-string.fromcharcode */ \ @@ -945,11 +922,6 @@ namespace internal { TFJ(StringPrototypeMatchAll, 1, kReceiver, kRegexp) \ /* ES6 #sec-string.prototype.localecompare */ \ CPP(StringPrototypeLocaleCompare) \ - /* ES6 #sec-string.prototype.padEnd */ \ - TFJ(StringPrototypePadEnd, SharedFunctionInfo::kDontAdaptArgumentsSentinel) \ - /* ES6 #sec-string.prototype.padStart */ \ - TFJ(StringPrototypePadStart, \ - SharedFunctionInfo::kDontAdaptArgumentsSentinel) \ /* ES6 #sec-string.prototype.replace */ \ TFJ(StringPrototypeReplace, 2, kReceiver, kSearch, kReplace) \ /* ES6 #sec-string.prototype.search */ \ @@ -1028,7 +1000,6 @@ namespace internal { TFC(WasmAtomicNotify, WasmAtomicNotify) \ TFC(WasmI32AtomicWait, WasmI32AtomicWait) \ TFC(WasmI64AtomicWait, WasmI64AtomicWait) \ - TFC(WasmCallJavaScript, CallTrampoline) \ TFC(WasmMemoryGrow, WasmMemoryGrow) \ TFC(WasmTableGet, WasmTableGet) \ TFC(WasmTableSet, WasmTableSet) \ @@ -1051,7 +1022,9 @@ namespace internal { TFS(ThrowWasmTrapElemSegmentDropped) \ TFS(ThrowWasmTrapTableOutOfBounds) \ TFC(WasmI64ToBigInt, I64ToBigInt) \ + TFC(WasmI32PairToBigInt, I32PairToBigInt) \ TFC(WasmBigIntToI64, BigIntToI64) \ + TFC(WasmBigIntToI32Pair, BigIntToI32Pair) \ \ /* WeakMap */ \ TFJ(WeakMapConstructor, SharedFunctionInfo::kDontAdaptArgumentsSentinel) \ @@ -1134,8 +1107,6 @@ namespace internal { \ /* String helpers */ \ TFS(StringAdd_CheckNone, kLeft, kRight) \ - TFS(StringAdd_ConvertLeft, kLeft, kRight) \ - TFS(StringAdd_ConvertRight, kLeft, kRight) \ TFS(SubString, kString, kFrom, kTo) \ \ /* Miscellaneous */ \ @@ -1344,7 +1315,6 @@ namespace internal { V(WasmAtomicNotify) \ V(WasmI32AtomicWait) \ V(WasmI64AtomicWait) \ - V(WasmCallJavaScript) \ V(WasmMemoryGrow) \ V(WasmTableGet) \ V(WasmTableSet) \ @@ -1356,7 +1326,9 @@ namespace internal { V(WasmRethrow) \ V(DoubleToI) \ V(WasmI64ToBigInt) \ - V(WasmBigIntToI64) + V(WasmI32PairToBigInt) \ + V(WasmBigIntToI64) \ + V(WasmBigIntToI32Pair) // The exception thrown in the following builtins are caught internally and will // not be propagated further or re-thrown diff --git a/deps/v8/src/builtins/builtins-function-gen.cc b/deps/v8/src/builtins/builtins-function-gen.cc index 411d9a6930..ee1f67d434 100644 --- a/deps/v8/src/builtins/builtins-function-gen.cc +++ b/deps/v8/src/builtins/builtins-function-gen.cc @@ -17,19 +17,20 @@ TF_BUILTIN(FastFunctionPrototypeBind, CodeStubAssembler) { // TODO(ishell): use constants from Descriptor once the JSFunction linkage // arguments are reordered. - Node* argc = Parameter(Descriptor::kJSActualArgumentsCount); + TNode<Int32T> argc = + UncheckedCast<Int32T>(Parameter(Descriptor::kJSActualArgumentsCount)); Node* context = Parameter(Descriptor::kContext); Node* new_target = Parameter(Descriptor::kJSNewTarget); CodeStubArguments args(this, ChangeInt32ToIntPtr(argc)); // Check that receiver has instance type of JS_FUNCTION_TYPE - Node* receiver = args.GetReceiver(); + TNode<Object> receiver = args.GetReceiver(); GotoIf(TaggedIsSmi(receiver), &slow); - Node* receiver_map = LoadMap(receiver); + TNode<Map> receiver_map = LoadMap(CAST(receiver)); { - Node* instance_type = LoadMapInstanceType(receiver_map); + TNode<Uint16T> instance_type = LoadMapInstanceType(receiver_map); GotoIfNot( Word32Or(InstanceTypeEqual(instance_type, JS_FUNCTION_TYPE), InstanceTypeEqual(instance_type, JS_BOUND_FUNCTION_TYPE)), @@ -45,35 +46,34 @@ TF_BUILTIN(FastFunctionPrototypeBind, CodeStubAssembler) { // AccessorInfo objects. In that case, their value can be recomputed even if // the actual value on the object changes. Comment("Check descriptor array length"); - TNode<DescriptorArray> descriptors = LoadMapDescriptors(receiver_map); // Minimum descriptor array length required for fast path. const int min_nof_descriptors = i::Max(JSFunction::kLengthDescriptorIndex, - JSFunction::kNameDescriptorIndex); - TNode<Int32T> nof_descriptors = LoadNumberOfDescriptors(descriptors); - GotoIf( - Int32LessThanOrEqual(nof_descriptors, Int32Constant(min_nof_descriptors)), - &slow); + JSFunction::kNameDescriptorIndex) + + 1; + TNode<Int32T> nof_descriptors = LoadNumberOfOwnDescriptors(receiver_map); + GotoIf(Int32LessThan(nof_descriptors, Int32Constant(min_nof_descriptors)), + &slow); // Check whether the length and name properties are still present as // AccessorInfo objects. In that case, their value can be recomputed even if // the actual value on the object changes. Comment("Check name and length properties"); { + TNode<DescriptorArray> descriptors = LoadMapDescriptors(receiver_map); const int length_index = JSFunction::kLengthDescriptorIndex; TNode<Name> maybe_length = LoadKeyByDescriptorEntry(descriptors, length_index); - GotoIf(WordNotEqual(maybe_length, LoadRoot(RootIndex::klength_string)), - &slow); + GotoIf(TaggedNotEqual(maybe_length, LengthStringConstant()), &slow); TNode<Object> maybe_length_accessor = LoadValueByDescriptorEntry(descriptors, length_index); GotoIf(TaggedIsSmi(maybe_length_accessor), &slow); - Node* length_value_map = LoadMap(CAST(maybe_length_accessor)); + TNode<Map> length_value_map = LoadMap(CAST(maybe_length_accessor)); GotoIfNot(IsAccessorInfoMap(length_value_map), &slow); const int name_index = JSFunction::kNameDescriptorIndex; TNode<Name> maybe_name = LoadKeyByDescriptorEntry(descriptors, name_index); - GotoIf(WordNotEqual(maybe_name, LoadRoot(RootIndex::kname_string)), &slow); + GotoIf(TaggedNotEqual(maybe_name, NameStringConstant()), &slow); TNode<Object> maybe_name_accessor = LoadValueByDescriptorEntry(descriptors, name_index); @@ -89,7 +89,7 @@ TF_BUILTIN(FastFunctionPrototypeBind, CodeStubAssembler) { { Label with_constructor(this); VariableList vars({&bound_function_map}, zone()); - Node* native_context = LoadNativeContext(context); + TNode<NativeContext> native_context = LoadNativeContext(context); Label map_done(this, vars); GotoIf(IsConstructorMap(receiver_map), &with_constructor); @@ -108,9 +108,10 @@ TF_BUILTIN(FastFunctionPrototypeBind, CodeStubAssembler) { // Verify that __proto__ matches that of a the target bound function. Comment("Verify that __proto__ matches target bound function"); - Node* prototype = LoadMapPrototype(receiver_map); - Node* expected_prototype = LoadMapPrototype(bound_function_map.value()); - GotoIf(WordNotEqual(prototype, expected_prototype), &slow); + TNode<HeapObject> prototype = LoadMapPrototype(receiver_map); + TNode<HeapObject> expected_prototype = + LoadMapPrototype(bound_function_map.value()); + GotoIf(TaggedNotEqual(prototype, expected_prototype), &slow); // Allocate the arguments array. Comment("Allocate the arguments array"); @@ -126,12 +127,13 @@ TF_BUILTIN(FastFunctionPrototypeBind, CodeStubAssembler) { VARIABLE(index, MachineType::PointerRepresentation()); index.Bind(IntPtrConstant(0)); VariableList foreach_vars({&index}, zone()); - args.ForEach(foreach_vars, - [this, elements, &index](Node* arg) { - StoreFixedArrayElement(elements, index.value(), arg); - Increment(&index); - }, - IntPtrConstant(1)); + args.ForEach( + foreach_vars, + [this, elements, &index](Node* arg) { + StoreFixedArrayElement(elements, index.value(), arg); + Increment(&index); + }, + IntPtrConstant(1)); argument_array.Bind(elements); Goto(&arguments_done); @@ -162,7 +164,7 @@ TF_BUILTIN(FastFunctionPrototypeBind, CodeStubAssembler) { // Allocate the resulting bound function. Comment("Allocate the resulting bound function"); { - Node* bound_function = Allocate(JSBoundFunction::kSize); + TNode<HeapObject> bound_function = Allocate(JSBoundFunction::kSize); StoreMapNoWriteBarrier(bound_function, bound_function_map.value()); StoreObjectFieldNoWriteBarrier( bound_function, JSBoundFunction::kBoundTargetFunctionOffset, receiver); @@ -172,7 +174,7 @@ TF_BUILTIN(FastFunctionPrototypeBind, CodeStubAssembler) { StoreObjectFieldNoWriteBarrier(bound_function, JSBoundFunction::kBoundArgumentsOffset, argument_array.value()); - Node* empty_fixed_array = EmptyFixedArrayConstant(); + TNode<FixedArray> empty_fixed_array = EmptyFixedArrayConstant(); StoreObjectFieldNoWriteBarrier( bound_function, JSObject::kPropertiesOrHashOffset, empty_fixed_array); StoreObjectFieldNoWriteBarrier(bound_function, JSObject::kElementsOffset, diff --git a/deps/v8/src/builtins/builtins-function.cc b/deps/v8/src/builtins/builtins-function.cc index f9a356f94b..f75014d034 100644 --- a/deps/v8/src/builtins/builtins-function.cc +++ b/deps/v8/src/builtins/builtins-function.cc @@ -93,6 +93,17 @@ MaybeHandle<Object> CreateDynamicFunction(Isolate* isolate, function->shared().set_name_should_print_as_anonymous(true); } + // The spec says that we have to wrap code created via the function + // constructor in e.g. 'function anonymous(' as above, including with extra + // line breaks. Ths is confusing when reporting stack traces from the eval'd + // code as the line number of the error is always reported with 2 extra line + // breaks e.g. line 1 is reported as line 3. We fix this up here by setting + // line_offset which is read by stack trace code. + Handle<Script> script(Script::cast(function->shared().script()), isolate); + if (script->line_offset() == 0) { + script->set_line_offset(-2); + } + // If new.target is equal to target then the function created // is already correctly setup and nothing else should be done // here. But if new.target is not equal to target then we are diff --git a/deps/v8/src/builtins/builtins-generator-gen.cc b/deps/v8/src/builtins/builtins-generator-gen.cc index 7e75bbcee0..d884c417fc 100644 --- a/deps/v8/src/builtins/builtins-generator-gen.cc +++ b/deps/v8/src/builtins/builtins-generator-gen.cc @@ -50,8 +50,8 @@ void GeneratorBuiltinsAssembler::GeneratorPrototypeResume( // Resume the {receiver} using our trampoline. VARIABLE(var_exception, MachineRepresentation::kTagged, UndefinedConstant()); Label if_exception(this, Label::kDeferred), if_final_return(this); - Node* result = CallStub(CodeFactory::ResumeGenerator(isolate()), context, - value, receiver); + TNode<Object> result = CallStub(CodeFactory::ResumeGenerator(isolate()), + context, value, receiver); // Make sure we close the generator if there was an exception. GotoIfException(result, &if_exception, &var_exception); @@ -115,12 +115,12 @@ void GeneratorBuiltinsAssembler::GeneratorPrototypeResume( TF_BUILTIN(GeneratorPrototypeNext, GeneratorBuiltinsAssembler) { const int kValueArg = 0; - Node* argc = + TNode<IntPtrT> argc = ChangeInt32ToIntPtr(Parameter(Descriptor::kJSActualArgumentsCount)); CodeStubArguments args(this, argc); - Node* receiver = args.GetReceiver(); - Node* value = args.GetOptionalArgumentValue(kValueArg); + TNode<Object> receiver = args.GetReceiver(); + TNode<Object> value = args.GetOptionalArgumentValue(kValueArg); Node* context = Parameter(Descriptor::kContext); GeneratorPrototypeResume(&args, receiver, value, context, @@ -132,12 +132,12 @@ TF_BUILTIN(GeneratorPrototypeNext, GeneratorBuiltinsAssembler) { TF_BUILTIN(GeneratorPrototypeReturn, GeneratorBuiltinsAssembler) { const int kValueArg = 0; - Node* argc = + TNode<IntPtrT> argc = ChangeInt32ToIntPtr(Parameter(Descriptor::kJSActualArgumentsCount)); CodeStubArguments args(this, argc); - Node* receiver = args.GetReceiver(); - Node* value = args.GetOptionalArgumentValue(kValueArg); + TNode<Object> receiver = args.GetReceiver(); + TNode<Object> value = args.GetOptionalArgumentValue(kValueArg); Node* context = Parameter(Descriptor::kContext); GeneratorPrototypeResume(&args, receiver, value, context, @@ -149,12 +149,12 @@ TF_BUILTIN(GeneratorPrototypeReturn, GeneratorBuiltinsAssembler) { TF_BUILTIN(GeneratorPrototypeThrow, GeneratorBuiltinsAssembler) { const int kExceptionArg = 0; - Node* argc = + TNode<IntPtrT> argc = ChangeInt32ToIntPtr(Parameter(Descriptor::kJSActualArgumentsCount)); CodeStubArguments args(this, argc); - Node* receiver = args.GetReceiver(); - Node* exception = args.GetOptionalArgumentValue(kExceptionArg); + TNode<Object> receiver = args.GetReceiver(); + TNode<Object> exception = args.GetOptionalArgumentValue(kExceptionArg); Node* context = Parameter(Descriptor::kContext); GeneratorPrototypeResume(&args, receiver, exception, context, diff --git a/deps/v8/src/builtins/builtins-global-gen.cc b/deps/v8/src/builtins/builtins-global-gen.cc index fa21f81650..ca29ab3cd2 100644 --- a/deps/v8/src/builtins/builtins-global-gen.cc +++ b/deps/v8/src/builtins/builtins-global-gen.cc @@ -35,7 +35,7 @@ TF_BUILTIN(GlobalIsFinite, CodeStubAssembler) { BIND(&if_numisheapnumber); { // Check if {num} contains a finite, non-NaN value. - Node* num_value = LoadHeapNumberValue(num); + TNode<Float64T> num_value = LoadHeapNumberValue(num); BranchIfFloat64IsNaN(Float64Sub(num_value, num_value), &return_false, &return_true); } @@ -81,7 +81,7 @@ TF_BUILTIN(GlobalIsNaN, CodeStubAssembler) { BIND(&if_numisheapnumber); { // Check if {num} contains a NaN. - Node* num_value = LoadHeapNumberValue(num); + TNode<Float64T> num_value = LoadHeapNumberValue(num); BranchIfFloat64IsNaN(num_value, &return_true, &return_false); } diff --git a/deps/v8/src/builtins/builtins-handler-gen.cc b/deps/v8/src/builtins/builtins-handler-gen.cc index 973356f569..eae8690f1f 100644 --- a/deps/v8/src/builtins/builtins-handler-gen.cc +++ b/deps/v8/src/builtins/builtins-handler-gen.cc @@ -66,9 +66,9 @@ void Builtins::Generate_KeyedStoreIC_Megamorphic( KeyedStoreGenericGenerator::Generate(state); } -void Builtins::Generate_StoreIC_Uninitialized( +void Builtins::Generate_StoreIC_NoFeedback( compiler::CodeAssemblerState* state) { - StoreICUninitializedGenerator::Generate(state); + StoreICNoFeedbackGenerator::Generate(state); } // TODO(mythria): Check if we can remove feedback vector and slot parameters in @@ -180,7 +180,7 @@ void HandlerBuiltinsAssembler::DispatchForElementsKindTransition( STATIC_ASSERT(arraysize(combined_elements_kinds) == arraysize(elements_kind_labels)); - TNode<Word32T> combined_elements_kind = + TNode<Int32T> combined_elements_kind = Word32Or(Word32Shl(from_kind, Int32Constant(kBitsPerByte)), to_kind); Switch(combined_elements_kind, &if_unknown_type, combined_elements_kinds, @@ -259,25 +259,27 @@ TF_BUILTIN(ElementsTransitionAndStore_NoTransitionHandleCOW, // All elements kinds handled by EmitElementStore. Specifically, this includes // fast elements and fixed typed array elements. -#define ELEMENTS_KINDS(V) \ - V(PACKED_SMI_ELEMENTS) \ - V(HOLEY_SMI_ELEMENTS) \ - V(PACKED_ELEMENTS) \ - V(PACKED_SEALED_ELEMENTS) \ - V(HOLEY_ELEMENTS) \ - V(HOLEY_SEALED_ELEMENTS) \ - V(PACKED_DOUBLE_ELEMENTS) \ - V(HOLEY_DOUBLE_ELEMENTS) \ - V(UINT8_ELEMENTS) \ - V(INT8_ELEMENTS) \ - V(UINT16_ELEMENTS) \ - V(INT16_ELEMENTS) \ - V(UINT32_ELEMENTS) \ - V(INT32_ELEMENTS) \ - V(FLOAT32_ELEMENTS) \ - V(FLOAT64_ELEMENTS) \ - V(UINT8_CLAMPED_ELEMENTS) \ - V(BIGUINT64_ELEMENTS) \ +#define ELEMENTS_KINDS(V) \ + V(PACKED_SMI_ELEMENTS) \ + V(HOLEY_SMI_ELEMENTS) \ + V(PACKED_ELEMENTS) \ + V(PACKED_NONEXTENSIBLE_ELEMENTS) \ + V(PACKED_SEALED_ELEMENTS) \ + V(HOLEY_ELEMENTS) \ + V(HOLEY_NONEXTENSIBLE_ELEMENTS) \ + V(HOLEY_SEALED_ELEMENTS) \ + V(PACKED_DOUBLE_ELEMENTS) \ + V(HOLEY_DOUBLE_ELEMENTS) \ + V(UINT8_ELEMENTS) \ + V(INT8_ELEMENTS) \ + V(UINT16_ELEMENTS) \ + V(INT16_ELEMENTS) \ + V(UINT32_ELEMENTS) \ + V(INT32_ELEMENTS) \ + V(FLOAT32_ELEMENTS) \ + V(FLOAT64_ELEMENTS) \ + V(UINT8_CLAMPED_ELEMENTS) \ + V(BIGUINT64_ELEMENTS) \ V(BIGINT64_ELEMENTS) void HandlerBuiltinsAssembler::DispatchByElementsKind( @@ -311,7 +313,7 @@ void HandlerBuiltinsAssembler::DispatchByElementsKind( BIND(&if_##KIND); \ { \ if (!FLAG_enable_sealed_frozen_elements_kind && \ - IsFrozenOrSealedElementsKindUnchecked(KIND)) { \ + IsAnyNonextensibleElementsKindUnchecked(KIND)) { \ /* Disable support for frozen or sealed elements kinds. */ \ Unreachable(); \ } else if (!handle_typed_elements_kind && \ @@ -403,7 +405,7 @@ TF_BUILTIN(LoadIC_FunctionPrototype, CodeStubAssembler) { Node* context = Parameter(Descriptor::kContext); Label miss(this, Label::kDeferred); - Return(LoadJSFunctionPrototype(receiver, &miss)); + Return(LoadJSFunctionPrototype(CAST(receiver), &miss)); BIND(&miss); TailCallRuntime(Runtime::kLoadIC_Miss, context, receiver, name, slot, vector); diff --git a/deps/v8/src/builtins/builtins-ic-gen.cc b/deps/v8/src/builtins/builtins-ic-gen.cc index ce944784ea..605b2a6b1a 100644 --- a/deps/v8/src/builtins/builtins-ic-gen.cc +++ b/deps/v8/src/builtins/builtins-ic-gen.cc @@ -23,7 +23,7 @@ namespace internal { IC_BUILTIN(LoadIC) IC_BUILTIN(LoadIC_Megamorphic) IC_BUILTIN(LoadIC_Noninlined) -IC_BUILTIN(LoadIC_Uninitialized) +IC_BUILTIN(LoadIC_NoFeedback) IC_BUILTIN(LoadICTrampoline) IC_BUILTIN(LoadICTrampoline_Megamorphic) IC_BUILTIN(KeyedLoadIC) diff --git a/deps/v8/src/builtins/builtins-internal-gen.cc b/deps/v8/src/builtins/builtins-internal-gen.cc index 8d22767b58..445c8c9517 100644 --- a/deps/v8/src/builtins/builtins-internal-gen.cc +++ b/deps/v8/src/builtins/builtins-internal-gen.cc @@ -35,7 +35,7 @@ TF_BUILTIN(CopyFastSmiOrObjectElements, CodeStubAssembler) { Node* object = Parameter(Descriptor::kObject); // Load the {object}s elements. - Node* source = LoadObjectField(object, JSObject::kElementsOffset); + TNode<Object> source = LoadObjectField(object, JSObject::kElementsOffset); Node* target = CloneFixedArray(source, ExtractFixedArrayFlag::kFixedArrays); StoreObjectField(object, JSObject::kElementsOffset, target); Return(target); @@ -104,7 +104,7 @@ TF_BUILTIN(NewArgumentsElements, CodeStubAssembler) { // the mapped elements (i.e. the first {mapped_count}) with the hole, but // make sure not to overshoot the {length} if some arguments are missing. TNode<IntPtrT> number_of_holes = IntPtrMin(mapped_count, length); - Node* the_hole = TheHoleConstant(); + TNode<Oddball> the_hole = TheHoleConstant(); // Fill the first elements up to {number_of_holes} with the hole. TVARIABLE(IntPtrT, var_index, IntPtrConstant(0)); @@ -116,7 +116,7 @@ TF_BUILTIN(NewArgumentsElements, CodeStubAssembler) { TNode<IntPtrT> index = var_index.value(); // Check if we are done. - GotoIf(WordEqual(index, number_of_holes), &done_loop1); + GotoIf(IntPtrEqual(index, number_of_holes), &done_loop1); // Store the hole into the {result}. StoreFixedArrayElement(result, index, the_hole, SKIP_WRITE_BARRIER); @@ -139,7 +139,7 @@ TF_BUILTIN(NewArgumentsElements, CodeStubAssembler) { TNode<IntPtrT> index = var_index.value(); // Check if we are done. - GotoIf(WordEqual(index, length), &done_loop2); + GotoIf(IntPtrEqual(index, length), &done_loop2); // Load the parameter at the given {index}. TNode<Object> value = BitcastWordToTagged( @@ -213,7 +213,7 @@ class RecordWriteCodeStubAssembler : public CodeStubAssembler { : CodeStubAssembler(state) {} Node* IsMarking() { - Node* is_marking_addr = ExternalConstant( + TNode<ExternalReference> is_marking_addr = ExternalConstant( ExternalReference::heap_is_marking_flag_address(this->isolate())); return Load(MachineType::Uint8(), is_marking_addr); } @@ -266,12 +266,12 @@ class RecordWriteCodeStubAssembler : public CodeStubAssembler { } } - Node* ShouldSkipFPRegs(Node* mode) { - return WordEqual(mode, SmiConstant(kDontSaveFPRegs)); + Node* ShouldSkipFPRegs(SloppyTNode<Object> mode) { + return TaggedEqual(mode, SmiConstant(kDontSaveFPRegs)); } - Node* ShouldEmitRememberSet(Node* remembered_set) { - return WordEqual(remembered_set, SmiConstant(EMIT_REMEMBERED_SET)); + Node* ShouldEmitRememberSet(SloppyTNode<Object> remembered_set) { + return TaggedEqual(remembered_set, SmiConstant(EMIT_REMEMBERED_SET)); } void CallCFunction1WithCallerSavedRegistersMode(MachineType return_type, @@ -323,26 +323,27 @@ class RecordWriteCodeStubAssembler : public CodeStubAssembler { void InsertToStoreBufferAndGoto(Node* isolate, Node* slot, Node* mode, Label* next) { - Node* store_buffer_top_addr = + TNode<ExternalReference> store_buffer_top_addr = ExternalConstant(ExternalReference::store_buffer_top(this->isolate())); Node* store_buffer_top = Load(MachineType::Pointer(), store_buffer_top_addr); StoreNoWriteBarrier(MachineType::PointerRepresentation(), store_buffer_top, slot); - Node* new_store_buffer_top = + TNode<WordT> new_store_buffer_top = IntPtrAdd(store_buffer_top, IntPtrConstant(kSystemPointerSize)); StoreNoWriteBarrier(MachineType::PointerRepresentation(), store_buffer_top_addr, new_store_buffer_top); - Node* test = WordAnd(new_store_buffer_top, - IntPtrConstant(Heap::store_buffer_mask_constant())); + TNode<WordT> test = + WordAnd(new_store_buffer_top, + IntPtrConstant(Heap::store_buffer_mask_constant())); Label overflow(this); - Branch(WordEqual(test, IntPtrConstant(0)), &overflow, next); + Branch(IntPtrEqual(test, IntPtrConstant(0)), &overflow, next); BIND(&overflow); { - Node* function = + TNode<ExternalReference> function = ExternalConstant(ExternalReference::store_buffer_overflow_function()); CallCFunction1WithCallerSavedRegistersMode(MachineType::Int32(), MachineType::Pointer(), @@ -395,7 +396,7 @@ TF_BUILTIN(RecordWrite, RecordWriteCodeStubAssembler) { BIND(&store_buffer_exit); { - Node* isolate_constant = + TNode<ExternalReference> isolate_constant = ExternalConstant(ExternalReference::isolate_address(isolate())); Node* fp_mode = Parameter(Descriptor::kFPMode); InsertToStoreBufferAndGoto(isolate_constant, slot, fp_mode, &exit); @@ -403,7 +404,7 @@ TF_BUILTIN(RecordWrite, RecordWriteCodeStubAssembler) { BIND(&store_buffer_incremental_wb); { - Node* isolate_constant = + TNode<ExternalReference> isolate_constant = ExternalConstant(ExternalReference::isolate_address(isolate())); Node* fp_mode = Parameter(Descriptor::kFPMode); InsertToStoreBufferAndGoto(isolate_constant, slot, fp_mode, @@ -435,9 +436,9 @@ TF_BUILTIN(RecordWrite, RecordWriteCodeStubAssembler) { BIND(&call_incremental_wb); { - Node* function = ExternalConstant( + TNode<ExternalReference> function = ExternalConstant( ExternalReference::incremental_marking_record_write_function()); - Node* isolate_constant = + TNode<ExternalReference> isolate_constant = ExternalConstant(ExternalReference::isolate_address(isolate())); Node* fp_mode = Parameter(Descriptor::kFPMode); TNode<IntPtrT> object = @@ -457,12 +458,12 @@ TF_BUILTIN(RecordWrite, RecordWriteCodeStubAssembler) { TF_BUILTIN(EphemeronKeyBarrier, RecordWriteCodeStubAssembler) { Label exit(this); - Node* function = ExternalConstant( + TNode<ExternalReference> function = ExternalConstant( ExternalReference::ephemeron_key_write_barrier_function()); - Node* isolate_constant = + TNode<ExternalReference> isolate_constant = ExternalConstant(ExternalReference::isolate_address(isolate())); Node* address = Parameter(Descriptor::kSlotAddress); - Node* object = BitcastTaggedToWord(Parameter(Descriptor::kObject)); + TNode<IntPtrT> object = BitcastTaggedToWord(Parameter(Descriptor::kObject)); Node* fp_mode = Parameter(Descriptor::kFPMode); CallCFunction3WithCallerSavedRegistersMode( MachineType::Int32(), MachineType::Pointer(), MachineType::Pointer(), @@ -495,7 +496,7 @@ class DeletePropertyBaseAssembler : public AccessorAssembler { GotoIf(IsSetWord32(details, PropertyDetails::kAttributesDontDeleteMask), dont_delete); // Overwrite the entry itself (see NameDictionary::SetEntry). - TNode<HeapObject> filler = TheHoleConstant(); + TNode<Oddball> filler = TheHoleConstant(); DCHECK(RootsTable::IsImmortalImmovable(RootIndex::kTheHoleValue)); StoreFixedArrayElement(properties, key_index, filler, SKIP_WRITE_BARRIER); StoreValueByKeyIndex<NameDictionary>(properties, key_index, filler, @@ -534,11 +535,12 @@ TF_BUILTIN(DeleteProperty, DeletePropertyBaseAssembler) { VARIABLE(var_index, MachineType::PointerRepresentation()); VARIABLE(var_unique, MachineRepresentation::kTagged, key); Label if_index(this), if_unique_name(this), if_notunique(this), - if_notfound(this), slow(this); + if_notfound(this), slow(this), if_proxy(this); GotoIf(TaggedIsSmi(receiver), &slow); TNode<Map> receiver_map = LoadMap(CAST(receiver)); - TNode<Int32T> instance_type = LoadMapInstanceType(receiver_map); + TNode<Uint16T> instance_type = LoadMapInstanceType(receiver_map); + GotoIf(InstanceTypeEqual(instance_type, JS_PROXY_TYPE), &if_proxy); GotoIf(IsCustomElementsReceiverInstanceType(instance_type), &slow); TryToName(key, &if_index, &var_index, &if_unique_name, &var_unique, &slow, &if_notunique); @@ -592,6 +594,14 @@ TF_BUILTIN(DeleteProperty, DeletePropertyBaseAssembler) { BIND(&if_notfound); Return(TrueConstant()); + BIND(&if_proxy); + { + TNode<Name> name = CAST(CallBuiltin(Builtins::kToName, context, key)); + GotoIf(IsPrivateSymbol(name), &slow); + TailCallBuiltin(Builtins::kProxyDeleteProperty, context, receiver, name, + language_mode); + } + BIND(&slow); { TailCallRuntime(Runtime::kDeleteProperty, context, receiver, key, @@ -622,7 +632,7 @@ class SetOrCopyDataPropertiesAssembler : public CodeStubAssembler { // Otherwise check if {source} is a proper JSObject, and if not, defer // to testing for non-empty strings below. TNode<Map> source_map = LoadMap(CAST(source)); - TNode<Int32T> source_instance_type = LoadMapInstanceType(source_map); + TNode<Uint16T> source_instance_type = LoadMapInstanceType(source_map); GotoIfNot(IsJSObjectInstanceType(source_instance_type), &if_sourcenotjsobject); @@ -670,7 +680,8 @@ class SetOrCopyDataPropertiesAssembler : public CodeStubAssembler { // handled explicitly by Object.assign() and CopyDataProperties. GotoIfNot(IsStringInstanceType(source_instance_type), &if_done); TNode<IntPtrT> source_length = LoadStringLengthAsWord(CAST(source)); - Branch(WordEqual(source_length, IntPtrConstant(0)), &if_done, if_runtime); + Branch(IntPtrEqual(source_length, IntPtrConstant(0)), &if_done, + if_runtime); } BIND(&if_done); @@ -686,7 +697,7 @@ TF_BUILTIN(CopyDataProperties, SetOrCopyDataPropertiesAssembler) { TNode<Object> source = CAST(Parameter(Descriptor::kSource)); TNode<Context> context = CAST(Parameter(Descriptor::kContext)); - CSA_ASSERT(this, WordNotEqual(target, source)); + CSA_ASSERT(this, TaggedNotEqual(target, source)); Label if_runtime(this, Label::kDeferred); Return(SetOrCopyDataProperties(context, target, source, &if_runtime, false)); @@ -980,7 +991,7 @@ TF_BUILTIN(GetProperty, CodeStubAssembler) { BIND(&if_proxy); { // Convert the {key} to a Name first. - Node* name = CallBuiltin(Builtins::kToName, context, key); + TNode<Object> name = CallBuiltin(Builtins::kToName, context, key); // The {object} is a JSProxy instance, look up the {name} on it, passing // {object} both as receiver and holder. If {name} is absent we can safely @@ -996,7 +1007,7 @@ TF_BUILTIN(GetPropertyWithReceiver, CodeStubAssembler) { Node* key = Parameter(Descriptor::kKey); Node* context = Parameter(Descriptor::kContext); Node* receiver = Parameter(Descriptor::kReceiver); - Node* on_non_existent = Parameter(Descriptor::kOnNonExistent); + TNode<Object> on_non_existent = CAST(Parameter(Descriptor::kOnNonExistent)); Label if_notfound(this), if_proxy(this, Label::kDeferred), if_slow(this, Label::kDeferred); @@ -1028,11 +1039,11 @@ TF_BUILTIN(GetPropertyWithReceiver, CodeStubAssembler) { BIND(&if_notfound); Label throw_reference_error(this); - GotoIf(WordEqual(on_non_existent, - SmiConstant(OnNonExistent::kThrowReferenceError)), + GotoIf(TaggedEqual(on_non_existent, + SmiConstant(OnNonExistent::kThrowReferenceError)), &throw_reference_error); - CSA_ASSERT(this, WordEqual(on_non_existent, - SmiConstant(OnNonExistent::kReturnUndefined))); + CSA_ASSERT(this, TaggedEqual(on_non_existent, + SmiConstant(OnNonExistent::kReturnUndefined))); Return(UndefinedConstant()); BIND(&throw_reference_error); @@ -1045,7 +1056,7 @@ TF_BUILTIN(GetPropertyWithReceiver, CodeStubAssembler) { BIND(&if_proxy); { // Convert the {key} to a Name first. - Node* name = CallBuiltin(Builtins::kToName, context, key); + TNode<Name> name = CAST(CallBuiltin(Builtins::kToName, context, key)); // Proxy cannot handle private symbol so bailout. GotoIf(IsPrivateSymbol(name), &if_slow); diff --git a/deps/v8/src/builtins/builtins-intl-gen.cc b/deps/v8/src/builtins/builtins-intl-gen.cc index 991790b490..1a9a3b7fd9 100644 --- a/deps/v8/src/builtins/builtins-intl-gen.cc +++ b/deps/v8/src/builtins/builtins-intl-gen.cc @@ -33,10 +33,7 @@ class IntlBuiltinsAssembler : public CodeStubAssembler { }; TF_BUILTIN(StringToLowerCaseIntl, IntlBuiltinsAssembler) { - Node* const string = Parameter(Descriptor::kString); - Node* const context = Parameter(Descriptor::kContext); - - CSA_ASSERT(this, IsString(string)); + TNode<String> const string = CAST(Parameter(Descriptor::kString)); Label call_c(this), return_string(this), runtime(this, Label::kDeferred); @@ -50,14 +47,14 @@ TF_BUILTIN(StringToLowerCaseIntl, IntlBuiltinsAssembler) { state(), string, ToDirectStringAssembler::kDontUnpackSlicedStrings); to_direct.TryToDirect(&runtime); - Node* const instance_type = to_direct.instance_type(); + TNode<Int32T> const instance_type = to_direct.instance_type(); CSA_ASSERT(this, Word32BinaryNot(IsIndirectStringInstanceType(instance_type))); GotoIfNot(IsOneByteStringInstanceType(instance_type), &runtime); // For short strings, do the conversion in CSA through the lookup table. - Node* const dst = AllocateSeqOneByteString(context, length); + TNode<String> const dst = AllocateSeqOneByteString(length); const int kMaxShortStringLength = 24; // Determined empirically. GotoIf(Uint32GreaterThan(length, Uint32Constant(kMaxShortStringLength)), @@ -68,31 +65,31 @@ TF_BUILTIN(StringToLowerCaseIntl, IntlBuiltinsAssembler) { VARIABLE(var_cursor, MachineType::PointerRepresentation(), IntPtrConstant(0)); - Node* const start_address = to_direct.PointerToData(&call_c); + TNode<RawPtrT> const start_address = to_direct.PointerToData(&call_c); TNode<IntPtrT> const end_address = Signed(IntPtrAdd(start_address, ChangeUint32ToWord(length))); - Node* const to_lower_table_addr = + TNode<ExternalReference> const to_lower_table_addr = ExternalConstant(ExternalReference::intl_to_latin1_lower_table()); VARIABLE(var_did_change, MachineRepresentation::kWord32, Int32Constant(0)); VariableList push_vars({&var_cursor, &var_did_change}, zone()); - BuildFastLoop(push_vars, start_address, end_address, - [=, &var_cursor, &var_did_change](Node* current) { - Node* c = Load(MachineType::Uint8(), current); - Node* lower = - Load(MachineType::Uint8(), to_lower_table_addr, - ChangeInt32ToIntPtr(c)); - StoreNoWriteBarrier(MachineRepresentation::kWord8, dst_ptr, - var_cursor.value(), lower); - - var_did_change.Bind(Word32Or(Word32NotEqual(c, lower), - var_did_change.value())); - - Increment(&var_cursor); - }, - kCharSize, INTPTR_PARAMETERS, IndexAdvanceMode::kPost); + BuildFastLoop( + push_vars, start_address, end_address, + [=, &var_cursor, &var_did_change](Node* current) { + TNode<Uint8T> c = Load<Uint8T>(current); + TNode<Uint8T> lower = + Load<Uint8T>(to_lower_table_addr, ChangeInt32ToIntPtr(c)); + StoreNoWriteBarrier(MachineRepresentation::kWord8, dst_ptr, + var_cursor.value(), lower); + + var_did_change.Bind( + Word32Or(Word32NotEqual(c, lower), var_did_change.value())); + + Increment(&var_cursor); + }, + kCharSize, INTPTR_PARAMETERS, IndexAdvanceMode::kPost); // Return the original string if it remained unchanged in order to preserve // e.g. internalization and private symbols (such as the preserved object @@ -106,9 +103,9 @@ TF_BUILTIN(StringToLowerCaseIntl, IntlBuiltinsAssembler) { // String ConvertOneByteToLower(String src, String dst); BIND(&call_c); { - Node* const src = to_direct.string(); + TNode<String> const src = to_direct.string(); - Node* const function_addr = + TNode<ExternalReference> const function_addr = ExternalConstant(ExternalReference::intl_convert_one_byte_to_lower()); MachineType type_tagged = MachineType::AnyTagged(); @@ -125,8 +122,8 @@ TF_BUILTIN(StringToLowerCaseIntl, IntlBuiltinsAssembler) { BIND(&runtime); { - Node* const result = CallRuntime(Runtime::kStringToLowerCaseIntl, - NoContextConstant(), string); + TNode<Object> const result = CallRuntime(Runtime::kStringToLowerCaseIntl, + NoContextConstant(), string); Return(result); } } diff --git a/deps/v8/src/builtins/builtins-iterator-gen.cc b/deps/v8/src/builtins/builtins-iterator-gen.cc index b3d8e27dbc..7bd5acfdcd 100644 --- a/deps/v8/src/builtins/builtins-iterator-gen.cc +++ b/deps/v8/src/builtins/builtins-iterator-gen.cc @@ -27,7 +27,7 @@ IteratorRecord IteratorBuiltinsAssembler::GetIterator(Node* context, Node* object, Label* if_exception, Variable* exception) { - Node* method = GetIteratorMethod(context, object); + TNode<Object> method = GetIteratorMethod(context, object); return GetIterator(context, object, method, if_exception, exception); } @@ -44,7 +44,8 @@ IteratorRecord IteratorBuiltinsAssembler::GetIterator(Node* context, BIND(&if_not_callable); { - Node* ret = CallRuntime(Runtime::kThrowIteratorError, context, object); + TNode<Object> ret = + CallRuntime(Runtime::kThrowIteratorError, context, object); GotoIfException(ret, if_exception, exception); Unreachable(); } @@ -61,13 +62,15 @@ IteratorRecord IteratorBuiltinsAssembler::GetIterator(Node* context, BIND(&if_notobject); { - Node* ret = CallRuntime(Runtime::kThrowSymbolIteratorInvalid, context); + TNode<Object> ret = + CallRuntime(Runtime::kThrowSymbolIteratorInvalid, context); GotoIfException(ret, if_exception, exception); Unreachable(); } BIND(&get_next); - Node* const next = GetProperty(context, iterator, factory()->next_string()); + TNode<Object> const next = + GetProperty(context, iterator, factory()->next_string()); GotoIfException(next, if_exception, exception); return IteratorRecord{TNode<JSReceiver>::UncheckedCast(iterator), @@ -76,8 +79,9 @@ IteratorRecord IteratorBuiltinsAssembler::GetIterator(Node* context, } TNode<JSReceiver> IteratorBuiltinsAssembler::IteratorStep( - Node* context, const IteratorRecord& iterator, Label* if_done, - Node* fast_iterator_result_map, Label* if_exception, Variable* exception) { + TNode<Context> context, const IteratorRecord& iterator, Label* if_done, + base::Optional<TNode<Map>> fast_iterator_result_map, Label* if_exception, + Variable* exception) { DCHECK_NOT_NULL(if_done); // 1. a. Let result be ? Invoke(iterator, "next", « »). Callable callable = CodeFactory::Call(isolate()); @@ -87,18 +91,18 @@ TNode<JSReceiver> IteratorBuiltinsAssembler::IteratorStep( // 3. If Type(result) is not Object, throw a TypeError exception. Label if_notobject(this, Label::kDeferred), return_result(this); GotoIf(TaggedIsSmi(result), &if_notobject); - Node* result_map = LoadMap(result); + TNode<Map> result_map = LoadMap(result); - if (fast_iterator_result_map != nullptr) { + if (fast_iterator_result_map) { // Fast iterator result case: Label if_generic(this); // 4. Return result. - GotoIfNot(WordEqual(result_map, fast_iterator_result_map), &if_generic); + GotoIfNot(TaggedEqual(result_map, *fast_iterator_result_map), &if_generic); // IteratorComplete // 2. Return ToBoolean(? Get(iterResult, "done")). - Node* done = LoadObjectField(result, JSIteratorResult::kDoneOffset); + TNode<Object> done = LoadObjectField(result, JSIteratorResult::kDoneOffset); BranchIfToBooleanIsTrue(done, if_done, &return_result); BIND(&if_generic); @@ -111,14 +115,14 @@ TNode<JSReceiver> IteratorBuiltinsAssembler::IteratorStep( // IteratorComplete // 2. Return ToBoolean(? Get(iterResult, "done")). - Node* done = GetProperty(context, result, factory()->done_string()); + TNode<Object> done = GetProperty(context, result, factory()->done_string()); GotoIfException(done, if_exception, exception); BranchIfToBooleanIsTrue(done, if_done, &return_result); } BIND(&if_notobject); { - Node* ret = + TNode<Object> ret = CallRuntime(Runtime::kThrowIteratorResultNotAnObject, context, result); GotoIfException(ret, if_exception, exception); Unreachable(); @@ -137,8 +141,8 @@ TNode<Object> IteratorBuiltinsAssembler::IteratorValue( if (fast_iterator_result_map) { // Fast iterator result case: Label if_generic(this); - Node* map = LoadMap(result); - GotoIfNot(WordEqual(map, *fast_iterator_result_map), &if_generic); + TNode<Map> map = LoadMap(result); + GotoIfNot(TaggedEqual(map, *fast_iterator_result_map), &if_generic); var_value = LoadObjectField(result, JSIteratorResult::kValueOffset); Goto(&exit); @@ -169,7 +173,7 @@ void IteratorBuiltinsAssembler::IteratorCloseOnException( CSA_ASSERT(this, IsJSReceiver(iterator.object)); // Let return be ? GetMethod(iterator, "return"). - Node* method = + TNode<Object> method = GetProperty(context, iterator.object, factory()->return_string()); GotoIfException(method, if_exception, exception); diff --git a/deps/v8/src/builtins/builtins-iterator-gen.h b/deps/v8/src/builtins/builtins-iterator-gen.h index db86c65385..2a0a510f73 100644 --- a/deps/v8/src/builtins/builtins-iterator-gen.h +++ b/deps/v8/src/builtins/builtins-iterator-gen.h @@ -36,15 +36,14 @@ class IteratorBuiltinsAssembler : public CodeStubAssembler { // result. // `fast_iterator_result_map` refers to the map for the JSIteratorResult // object, loaded from the native context. - TNode<JSReceiver> IteratorStep(Node* context, const IteratorRecord& iterator, - Label* if_done, - Node* fast_iterator_result_map = nullptr, - Label* if_exception = nullptr, - Variable* exception = nullptr); - - TNode<JSReceiver> IteratorStep(Node* context, const IteratorRecord& iterator, - Node* fast_iterator_result_map, - Label* if_done) { + TNode<JSReceiver> IteratorStep( + TNode<Context> context, const IteratorRecord& iterator, Label* if_done, + base::Optional<TNode<Map>> fast_iterator_result_map = base::nullopt, + Label* if_exception = nullptr, Variable* exception = nullptr); + + TNode<JSReceiver> IteratorStep( + TNode<Context> context, const IteratorRecord& iterator, + base::Optional<TNode<Map>> fast_iterator_result_map, Label* if_done) { return IteratorStep(context, iterator, if_done, fast_iterator_result_map); } diff --git a/deps/v8/src/builtins/builtins-lazy-gen.cc b/deps/v8/src/builtins/builtins-lazy-gen.cc index c73cbee1bc..95d5229974 100644 --- a/deps/v8/src/builtins/builtins-lazy-gen.cc +++ b/deps/v8/src/builtins/builtins-lazy-gen.cc @@ -146,8 +146,8 @@ void LazyBuiltinsAssembler::CompileLazy(TNode<JSFunction> function) { 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)))); + CSA_ASSERT(this, TaggedNotEqual(sfi_code, HeapConstant(BUILTIN_CODE( + isolate(), CompileLazy)))); StoreObjectField(function, JSFunction::kCodeOffset, sfi_code); GenerateTailCallToJSCode(sfi_code, function); diff --git a/deps/v8/src/builtins/builtins-math-gen.cc b/deps/v8/src/builtins/builtins-math-gen.cc index 46195e74ed..42d0162f38 100644 --- a/deps/v8/src/builtins/builtins-math-gen.cc +++ b/deps/v8/src/builtins/builtins-math-gen.cc @@ -8,6 +8,7 @@ #include "src/builtins/builtins.h" #include "src/codegen/code-factory.h" #include "src/codegen/code-stub-assembler.h" +#include "src/objects/fixed-array.h" namespace v8 { namespace internal { @@ -39,7 +40,7 @@ TF_BUILTIN(MathAbs, CodeStubAssembler) { // check if support abs function if (IsIntPtrAbsWithOverflowSupported()) { - Node* pair = IntPtrAbsWithOverflow(x); + TNode<PairT<IntPtrT, BoolT>> pair = IntPtrAbsWithOverflow(x); Node* overflow = Projection(1, pair); GotoIf(overflow, &if_overflow); @@ -79,9 +80,9 @@ TF_BUILTIN(MathAbs, CodeStubAssembler) { BIND(&if_xisheapnumber); { - Node* x_value = LoadHeapNumberValue(x); - Node* value = Float64Abs(x_value); - Node* result = AllocateHeapNumberWithValue(value); + TNode<Float64T> x_value = LoadHeapNumberValue(x); + TNode<Float64T> value = Float64Abs(x_value); + TNode<HeapNumber> result = AllocateHeapNumberWithValue(value); Return(result); } @@ -125,9 +126,9 @@ void MathBuiltinsAssembler::MathRoundingOperation( BIND(&if_xisheapnumber); { - Node* x_value = LoadHeapNumberValue(x); - Node* value = (this->*float64op)(x_value); - Node* result = ChangeFloat64ToTagged(value); + TNode<Float64T> x_value = LoadHeapNumberValue(x); + TNode<Float64T> value = (this->*float64op)(x_value); + TNode<Number> result = ChangeFloat64ToTagged(value); Return(result); } @@ -182,8 +183,8 @@ TF_BUILTIN(MathImul, CodeStubAssembler) { Node* y = Parameter(Descriptor::kY); Node* x_value = TruncateTaggedToWord32(context, x); Node* y_value = TruncateTaggedToWord32(context, y); - Node* value = Int32Mul(x_value, y_value); - Node* result = ChangeInt32ToTagged(value); + TNode<Int32T> value = Signed(Int32Mul(x_value, y_value)); + TNode<Number> result = ChangeInt32ToTagged(value); Return(result); } @@ -192,7 +193,7 @@ CodeStubAssembler::Node* MathBuiltinsAssembler::MathPow(Node* context, Node* exponent) { Node* base_value = TruncateTaggedToFloat64(context, base); Node* exponent_value = TruncateTaggedToFloat64(context, exponent); - Node* value = Float64Pow(base_value, exponent_value); + TNode<Float64T> value = Float64Pow(base_value, exponent_value); return ChangeFloat64ToTagged(value); } @@ -205,7 +206,7 @@ TF_BUILTIN(MathPow, MathBuiltinsAssembler) { // ES6 #sec-math.random TF_BUILTIN(MathRandom, CodeStubAssembler) { Node* context = Parameter(Descriptor::kContext); - Node* native_context = LoadNativeContext(context); + TNode<NativeContext> native_context = LoadNativeContext(context); // Load cache index. TVARIABLE(Smi, smi_index); @@ -217,9 +218,9 @@ TF_BUILTIN(MathRandom, CodeStubAssembler) { GotoIf(SmiAbove(smi_index.value(), SmiConstant(0)), &if_cached); // Cache exhausted, populate the cache. Return value is the new index. - Node* const refill_math_random = + TNode<ExternalReference> const refill_math_random = ExternalConstant(ExternalReference::refill_math_random()); - Node* const isolate_ptr = + TNode<ExternalReference> const isolate_ptr = ExternalConstant(ExternalReference::isolate_address(isolate())); MachineType type_tagged = MachineType::AnyTagged(); MachineType type_ptr = MachineType::Pointer(); @@ -236,9 +237,9 @@ TF_BUILTIN(MathRandom, CodeStubAssembler) { new_smi_index); // Load and return next cached random number. - Node* array = - LoadContextElement(native_context, Context::MATH_RANDOM_CACHE_INDEX); - Node* random = LoadFixedDoubleArrayElement( + TNode<FixedDoubleArray> array = CAST( + LoadContextElement(native_context, Context::MATH_RANDOM_CACHE_INDEX)); + TNode<Float64T> random = LoadFixedDoubleArrayElement( array, new_smi_index, MachineType::Float64(), 0, SMI_PARAMETERS); Return(AllocateHeapNumberWithValue(random)); } diff --git a/deps/v8/src/builtins/builtins-math.cc b/deps/v8/src/builtins/builtins-math.cc deleted file mode 100644 index cce780ab9f..0000000000 --- a/deps/v8/src/builtins/builtins-math.cc +++ /dev/null @@ -1,61 +0,0 @@ -// Copyright 2016 the V8 project authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "src/builtins/builtins-utils.h" -#include "src/builtins/builtins.h" -#include "src/logging/counters.h" -#include "src/objects/objects-inl.h" - -namespace v8 { -namespace internal { - -// ----------------------------------------------------------------------------- -// ES6 section 20.2.2 Function Properties of the Math Object - -// ES6 section 20.2.2.18 Math.hypot ( value1, value2, ...values ) -BUILTIN(MathHypot) { - HandleScope scope(isolate); - int const length = args.length() - 1; - if (length == 0) return Smi::kZero; - DCHECK_LT(0, length); - double max = 0; - std::vector<double> abs_values; - abs_values.reserve(length); - for (int i = 0; i < length; i++) { - Handle<Object> x = args.at(i + 1); - ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, x, - Object::ToNumber(isolate, x)); - double abs_value = std::abs(x->Number()); - abs_values.push_back(abs_value); - // Use negation here to make sure that {max} is NaN - // in the end in case any of the arguments was NaN. - if (!(abs_value <= max)) { - max = abs_value; - } - } - - if (max == 0) { - return Smi::kZero; - } else if (max == V8_INFINITY) { - return ReadOnlyRoots(isolate).infinity_value(); - } - DCHECK(!(max <= 0)); - - // Kahan summation to avoid rounding errors. - // Normalize the numbers to the largest one to avoid overflow. - double sum = 0; - double compensation = 0; - for (int i = 0; i < length; i++) { - double n = abs_values[i] / max; - double summand = n * n - compensation; - double preliminary = sum + summand; - compensation = (preliminary - sum) - summand; - sum = preliminary; - } - - return *isolate->factory()->NewNumber(std::sqrt(sum) * max); -} - -} // namespace internal -} // namespace v8 diff --git a/deps/v8/src/builtins/builtins-microtask-queue-gen.cc b/deps/v8/src/builtins/builtins-microtask-queue-gen.cc index 4987787c35..427fd6edb6 100644 --- a/deps/v8/src/builtins/builtins-microtask-queue-gen.cc +++ b/deps/v8/src/builtins/builtins-microtask-queue-gen.cc @@ -123,7 +123,7 @@ void MicrotaskQueueBuiltinsAssembler::RunSingleMicrotask( StoreRoot(RootIndex::kCurrentMicrotask, microtask); TNode<IntPtrT> saved_entered_context_count = GetEnteredContextCount(); TNode<Map> microtask_map = LoadMap(microtask); - TNode<Int32T> microtask_type = LoadMapInstanceType(microtask_map); + TNode<Uint16T> microtask_type = LoadMapInstanceType(microtask_map); VARIABLE(var_exception, MachineRepresentation::kTagged, TheHoleConstant()); Label if_exception(this, Label::kDeferred); @@ -131,21 +131,15 @@ void MicrotaskQueueBuiltinsAssembler::RunSingleMicrotask( is_promise_fulfill_reaction_job(this), is_promise_reject_reaction_job(this), is_promise_resolve_thenable_job(this), - is_finalization_group_cleanup_job(this), is_unreachable(this, Label::kDeferred), done(this); - int32_t case_values[] = {CALLABLE_TASK_TYPE, - CALLBACK_TASK_TYPE, + int32_t case_values[] = {CALLABLE_TASK_TYPE, CALLBACK_TASK_TYPE, PROMISE_FULFILL_REACTION_JOB_TASK_TYPE, PROMISE_REJECT_REACTION_JOB_TASK_TYPE, - PROMISE_RESOLVE_THENABLE_JOB_TASK_TYPE, - FINALIZATION_GROUP_CLEANUP_JOB_TASK_TYPE}; - Label* case_labels[] = {&is_callable, - &is_callback, - &is_promise_fulfill_reaction_job, - &is_promise_reject_reaction_job, - &is_promise_resolve_thenable_job, - &is_finalization_group_cleanup_job}; + PROMISE_RESOLVE_THENABLE_JOB_TASK_TYPE}; + Label* case_labels[] = { + &is_callable, &is_callback, &is_promise_fulfill_reaction_job, + &is_promise_reject_reaction_job, &is_promise_resolve_thenable_job}; static_assert(arraysize(case_values) == arraysize(case_labels), ""); Switch(microtask_type, &is_unreachable, case_values, case_labels, arraysize(case_labels)); @@ -155,7 +149,7 @@ void MicrotaskQueueBuiltinsAssembler::RunSingleMicrotask( // Enter the context of the {microtask}. TNode<Context> microtask_context = LoadObjectField<Context>(microtask, CallableTask::kContextOffset); - TNode<Context> native_context = LoadNativeContext(microtask_context); + TNode<NativeContext> native_context = LoadNativeContext(microtask_context); PrepareForContext(native_context, &done); TNode<JSReceiver> callable = @@ -171,9 +165,9 @@ void MicrotaskQueueBuiltinsAssembler::RunSingleMicrotask( BIND(&is_callback); { - Node* const microtask_callback = + TNode<Object> const microtask_callback = LoadObjectField(microtask, CallbackTask::kCallbackOffset); - Node* const microtask_data = + TNode<Object> const microtask_data = LoadObjectField(microtask, CallbackTask::kDataOffset); // If this turns out to become a bottleneck because of the calls @@ -186,7 +180,7 @@ void MicrotaskQueueBuiltinsAssembler::RunSingleMicrotask( // But from our current measurements it doesn't seem to be a // serious performance problem, even if the microtask is full // of CallHandlerTasks (which is not a realistic use case anyways). - Node* const result = + TNode<Object> const result = CallRuntime(Runtime::kRunMicrotaskCallback, current_context, microtask_callback, microtask_data); GotoIfException(result, &if_exception, &var_exception); @@ -198,17 +192,17 @@ void MicrotaskQueueBuiltinsAssembler::RunSingleMicrotask( // Enter the context of the {microtask}. TNode<Context> microtask_context = LoadObjectField<Context>( microtask, PromiseResolveThenableJobTask::kContextOffset); - TNode<Context> native_context = LoadNativeContext(microtask_context); + TNode<NativeContext> native_context = LoadNativeContext(microtask_context); PrepareForContext(native_context, &done); - Node* const promise_to_resolve = LoadObjectField( + TNode<Object> const promise_to_resolve = LoadObjectField( microtask, PromiseResolveThenableJobTask::kPromiseToResolveOffset); - Node* const then = + TNode<Object> const then = LoadObjectField(microtask, PromiseResolveThenableJobTask::kThenOffset); - Node* const thenable = LoadObjectField( + TNode<Object> const thenable = LoadObjectField( microtask, PromiseResolveThenableJobTask::kThenableOffset); - Node* const result = + TNode<Object> const result = CallBuiltin(Builtins::kPromiseResolveThenableJob, native_context, promise_to_resolve, thenable, then); GotoIfException(result, &if_exception, &var_exception); @@ -222,21 +216,21 @@ void MicrotaskQueueBuiltinsAssembler::RunSingleMicrotask( // Enter the context of the {microtask}. TNode<Context> microtask_context = LoadObjectField<Context>( microtask, PromiseReactionJobTask::kContextOffset); - TNode<Context> native_context = LoadNativeContext(microtask_context); + TNode<NativeContext> native_context = LoadNativeContext(microtask_context); PrepareForContext(native_context, &done); - Node* const argument = + TNode<Object> const argument = LoadObjectField(microtask, PromiseReactionJobTask::kArgumentOffset); - Node* const handler = + TNode<Object> const handler = LoadObjectField(microtask, PromiseReactionJobTask::kHandlerOffset); - Node* const promise_or_capability = LoadObjectField( - microtask, PromiseReactionJobTask::kPromiseOrCapabilityOffset); + TNode<HeapObject> const promise_or_capability = CAST(LoadObjectField( + microtask, PromiseReactionJobTask::kPromiseOrCapabilityOffset)); // Run the promise before/debug hook if enabled. RunPromiseHook(Runtime::kPromiseHookBefore, microtask_context, promise_or_capability); - Node* const result = + TNode<Object> const result = CallBuiltin(Builtins::kPromiseFulfillReactionJob, microtask_context, argument, handler, promise_or_capability); GotoIfException(result, &if_exception, &var_exception); @@ -255,21 +249,21 @@ void MicrotaskQueueBuiltinsAssembler::RunSingleMicrotask( // Enter the context of the {microtask}. TNode<Context> microtask_context = LoadObjectField<Context>( microtask, PromiseReactionJobTask::kContextOffset); - TNode<Context> native_context = LoadNativeContext(microtask_context); + TNode<NativeContext> native_context = LoadNativeContext(microtask_context); PrepareForContext(native_context, &done); - Node* const argument = + TNode<Object> const argument = LoadObjectField(microtask, PromiseReactionJobTask::kArgumentOffset); - Node* const handler = + TNode<Object> const handler = LoadObjectField(microtask, PromiseReactionJobTask::kHandlerOffset); - Node* const promise_or_capability = LoadObjectField( - microtask, PromiseReactionJobTask::kPromiseOrCapabilityOffset); + TNode<HeapObject> const promise_or_capability = CAST(LoadObjectField( + microtask, PromiseReactionJobTask::kPromiseOrCapabilityOffset)); // Run the promise before/debug hook if enabled. RunPromiseHook(Runtime::kPromiseHookBefore, microtask_context, promise_or_capability); - Node* const result = + TNode<Object> const result = CallBuiltin(Builtins::kPromiseRejectReactionJob, microtask_context, argument, handler, promise_or_capability); GotoIfException(result, &if_exception, &var_exception); @@ -283,26 +277,6 @@ void MicrotaskQueueBuiltinsAssembler::RunSingleMicrotask( Goto(&done); } - BIND(&is_finalization_group_cleanup_job); - { - // Enter the context of the {finalization_group}. - TNode<JSFinalizationGroup> finalization_group = - LoadObjectField<JSFinalizationGroup>( - microtask, - FinalizationGroupCleanupJobTask::kFinalizationGroupOffset); - TNode<Context> native_context = LoadObjectField<Context>( - finalization_group, JSFinalizationGroup::kNativeContextOffset); - PrepareForContext(native_context, &done); - - Node* const result = CallRuntime(Runtime::kFinalizationGroupCleanupJob, - native_context, finalization_group); - - GotoIfException(result, &if_exception, &var_exception); - RewindEnteredContext(saved_entered_context_count); - SetCurrentContext(current_context); - Goto(&done); - } - BIND(&is_unreachable); Unreachable(); @@ -407,7 +381,7 @@ void MicrotaskQueueBuiltinsAssembler::EnterMicrotaskContext( BIND(&if_grow); { - Node* function = + TNode<ExternalReference> function = ExternalConstant(ExternalReference::call_enter_context_function()); CallCFunction(function, MachineType::Int32(), std::make_pair(MachineType::Pointer(), hsi), @@ -475,7 +449,7 @@ TF_BUILTIN(EnqueueMicrotask, MicrotaskQueueBuiltinsAssembler) { TNode<Microtask> microtask = UncheckedCast<Microtask>(Parameter(Descriptor::kMicrotask)); TNode<Context> context = CAST(Parameter(Descriptor::kContext)); - TNode<Context> native_context = LoadNativeContext(context); + TNode<NativeContext> native_context = LoadNativeContext(context); TNode<RawPtrT> microtask_queue = GetMicrotaskQueue(native_context); // Do not store the microtask if MicrotaskQueue is not available, that may @@ -506,9 +480,9 @@ TF_BUILTIN(EnqueueMicrotask, MicrotaskQueueBuiltinsAssembler) { // implementation to grow the buffer. BIND(&if_grow); { - Node* isolate_constant = + TNode<ExternalReference> isolate_constant = ExternalConstant(ExternalReference::isolate_address(isolate())); - Node* function = + TNode<ExternalReference> function = ExternalConstant(ExternalReference::call_enqueue_microtask_function()); CallCFunction(function, MachineType::AnyTagged(), std::make_pair(MachineType::Pointer(), isolate_constant), diff --git a/deps/v8/src/builtins/builtins-number-gen.cc b/deps/v8/src/builtins/builtins-number-gen.cc index f5c4477c23..2aa996eba0 100644 --- a/deps/v8/src/builtins/builtins-number-gen.cc +++ b/deps/v8/src/builtins/builtins-number-gen.cc @@ -83,7 +83,7 @@ TF_BUILTIN(NumberIsFinite, CodeStubAssembler) { GotoIfNot(IsHeapNumber(number), &return_false); // Check if {number} contains a finite, non-NaN value. - Node* number_value = LoadHeapNumberValue(number); + TNode<Float64T> number_value = LoadHeapNumberValue(number); BranchIfFloat64IsNaN(Float64Sub(number_value, number_value), &return_false, &return_true); @@ -95,7 +95,7 @@ TF_BUILTIN(NumberIsFinite, CodeStubAssembler) { } TF_BUILTIN(AllocateHeapNumber, CodeStubAssembler) { - Node* result = AllocateHeapNumber(); + TNode<HeapNumber> result = AllocateHeapNumber(); Return(result); } @@ -118,7 +118,7 @@ TF_BUILTIN(NumberIsNaN, CodeStubAssembler) { GotoIfNot(IsHeapNumber(number), &return_false); // Check if {number} contains a NaN value. - Node* number_value = LoadHeapNumberValue(number); + TNode<Float64T> number_value = LoadHeapNumberValue(number); BranchIfFloat64IsNaN(number_value, &return_true, &return_false); BIND(&return_true); @@ -162,8 +162,8 @@ TF_BUILTIN(NumberParseFloat, CodeStubAssembler) { { // The {input} is a HeapObject, check if it's already a String. Label if_inputisstring(this), if_inputisnotstring(this); - Node* input_map = LoadMap(input); - Node* input_instance_type = LoadMapInstanceType(input_map); + TNode<Map> input_map = LoadMap(input); + TNode<Uint16T> input_instance_type = LoadMapInstanceType(input_map); Branch(IsStringInstanceType(input_instance_type), &if_inputisstring, &if_inputisnotstring); @@ -172,7 +172,7 @@ TF_BUILTIN(NumberParseFloat, CodeStubAssembler) { // The {input} is already a String, check if {input} contains // a cached array index. Label if_inputcached(this), if_inputnotcached(this); - Node* input_hash = LoadNameHashField(input); + TNode<Uint32T> input_hash = LoadNameHashField(input); Branch(IsClearWord32(input_hash, Name::kDoesNotContainCachedArrayIndexMask), &if_inputcached, &if_inputnotcached); @@ -180,9 +180,9 @@ TF_BUILTIN(NumberParseFloat, CodeStubAssembler) { BIND(&if_inputcached); { // Just return the {input}s cached array index. - Node* input_array_index = + TNode<UintPtrT> input_array_index = DecodeWordFromWord32<String::ArrayIndexValueBits>(input_hash); - Return(SmiTag(input_array_index)); + Return(SmiTag(Signed(input_array_index))); } BIND(&if_inputnotcached); @@ -204,7 +204,7 @@ TF_BUILTIN(NumberParseFloat, CodeStubAssembler) { { // The {input} is already a Number, take care of -0. Label if_inputiszero(this), if_inputisnotzero(this); - Node* input_value = LoadHeapNumberValue(input); + TNode<Float64T> input_value = LoadHeapNumberValue(input); Branch(Float64Equal(input_value, Float64Constant(0.0)), &if_inputiszero, &if_inputisnotzero); @@ -229,15 +229,15 @@ TF_BUILTIN(NumberParseFloat, CodeStubAssembler) { // ES6 #sec-number.parseint TF_BUILTIN(ParseInt, CodeStubAssembler) { - Node* context = Parameter(Descriptor::kContext); - Node* input = Parameter(Descriptor::kString); - Node* radix = Parameter(Descriptor::kRadix); + TNode<Context> context = CAST(Parameter(Descriptor::kContext)); + TNode<Object> input = CAST(Parameter(Descriptor::kString)); + TNode<Object> radix = CAST(Parameter(Descriptor::kRadix)); // Check if {radix} is treated as 10 (i.e. undefined, 0 or 10). Label if_radix10(this), if_generic(this, Label::kDeferred); GotoIf(IsUndefined(radix), &if_radix10); - GotoIf(WordEqual(radix, SmiConstant(10)), &if_radix10); - GotoIf(WordEqual(radix, SmiConstant(0)), &if_radix10); + GotoIf(TaggedEqual(radix, SmiConstant(10)), &if_radix10); + GotoIf(TaggedEqual(radix, SmiConstant(0)), &if_radix10); Goto(&if_generic); BIND(&if_radix10); @@ -246,9 +246,9 @@ TF_BUILTIN(ParseInt, CodeStubAssembler) { Label if_inputissmi(this), if_inputisheapnumber(this), if_inputisstring(this); GotoIf(TaggedIsSmi(input), &if_inputissmi); - Node* input_map = LoadMap(input); + TNode<Map> input_map = LoadMap(CAST(input)); GotoIf(IsHeapNumberMap(input_map), &if_inputisheapnumber); - Node* input_instance_type = LoadMapInstanceType(input_map); + TNode<Uint16T> input_instance_type = LoadMapInstanceType(input_map); Branch(IsStringInstanceType(input_instance_type), &if_inputisstring, &if_generic); @@ -262,15 +262,16 @@ TF_BUILTIN(ParseInt, CodeStubAssembler) { { // Check if the {input} value is in Signed32 range. Label if_inputissigned32(this); - Node* input_value = LoadHeapNumberValue(input); - Node* input_value32 = TruncateFloat64ToWord32(input_value); + TNode<Float64T> input_value = LoadHeapNumberValue(CAST(input)); + TNode<Int32T> input_value32 = + Signed(TruncateFloat64ToWord32(input_value)); GotoIf(Float64Equal(input_value, ChangeInt32ToFloat64(input_value32)), &if_inputissigned32); // Check if the absolute {input} value is in the [1,1<<31[ range. // Take the generic path for the range [0,1[ because the result // could be -0. - Node* input_value_abs = Float64Abs(input_value); + TNode<Float64T> input_value_abs = Float64Abs(input_value); GotoIfNot(Float64LessThan(input_value_abs, Float64Constant(1u << 31)), &if_generic); @@ -279,28 +280,29 @@ TF_BUILTIN(ParseInt, CodeStubAssembler) { // Return the truncated int32 value, and return the tagged result. BIND(&if_inputissigned32); - Node* result = ChangeInt32ToTagged(input_value32); + TNode<Number> result = ChangeInt32ToTagged(input_value32); Return(result); } BIND(&if_inputisstring); { // Check if the String {input} has a cached array index. - Node* input_hash = LoadNameHashField(input); + TNode<Uint32T> input_hash = LoadNameHashField(CAST(input)); GotoIf(IsSetWord32(input_hash, Name::kDoesNotContainCachedArrayIndexMask), &if_generic); // Return the cached array index as result. - Node* input_index = + TNode<UintPtrT> input_index = DecodeWordFromWord32<String::ArrayIndexValueBits>(input_hash); - Node* result = SmiTag(input_index); + TNode<Smi> result = SmiTag(Signed(input_index)); Return(result); } } BIND(&if_generic); { - Node* result = CallRuntime(Runtime::kStringParseInt, context, input, radix); + TNode<Object> result = + CallRuntime(Runtime::kStringParseInt, context, input, radix); Return(result); } } @@ -318,8 +320,8 @@ TF_BUILTIN(NumberPrototypeValueOf, CodeStubAssembler) { TNode<Context> context = CAST(Parameter(Descriptor::kContext)); TNode<Object> receiver = CAST(Parameter(Descriptor::kReceiver)); - Node* result = ToThisValue(context, receiver, PrimitiveType::kNumber, - "Number.prototype.valueOf"); + TNode<Object> result = ToThisValue(context, receiver, PrimitiveType::kNumber, + "Number.prototype.valueOf"); Return(result); } @@ -406,7 +408,7 @@ TF_BUILTIN(Add, AddStubAssembler) { BIND(&if_right_heapobject); { - Node* right_map = LoadMap(right); + TNode<Map> right_map = LoadMap(right); Label if_right_not_number(this, Label::kDeferred); GotoIfNot(IsHeapNumberMap(right_map), &if_right_not_number); @@ -418,7 +420,7 @@ TF_BUILTIN(Add, AddStubAssembler) { BIND(&if_right_not_number); { - Node* right_instance_type = LoadMapInstanceType(right_map); + TNode<Uint16T> right_instance_type = LoadMapInstanceType(right_map); GotoIf(IsStringInstanceType(right_instance_type), &string_add_convert_left); GotoIf(IsBigIntInstanceType(right_instance_type), &do_bigint_add); @@ -429,7 +431,7 @@ TF_BUILTIN(Add, AddStubAssembler) { BIND(&if_left_heapobject); { - Node* left_map = LoadMap(left); + TNode<Map> left_map = LoadMap(left); Label if_right_smi(this), if_right_heapobject(this); Branch(TaggedIsSmi(right), &if_right_smi, &if_right_heapobject); @@ -445,7 +447,7 @@ TF_BUILTIN(Add, AddStubAssembler) { BIND(&if_left_not_number); { - Node* left_instance_type = LoadMapInstanceType(left_map); + TNode<Uint16T> left_instance_type = LoadMapInstanceType(left_map); GotoIf(IsStringInstanceType(left_instance_type), &string_add_convert_right); GotoIf(IsBigIntInstanceType(left_instance_type), &do_bigint_add); @@ -456,7 +458,7 @@ TF_BUILTIN(Add, AddStubAssembler) { BIND(&if_right_heapobject); { - Node* right_map = LoadMap(right); + TNode<Map> right_map = LoadMap(right); Label if_left_number(this), if_left_not_number(this, Label::kDeferred); Branch(IsHeapNumberMap(left_map), &if_left_number, &if_left_not_number); @@ -473,7 +475,7 @@ TF_BUILTIN(Add, AddStubAssembler) { BIND(&if_right_not_number); { - Node* right_instance_type = LoadMapInstanceType(right_map); + TNode<Uint16T> right_instance_type = LoadMapInstanceType(right_map); GotoIf(IsStringInstanceType(right_instance_type), &string_add_convert_left); GotoIf(IsBigIntInstanceType(right_instance_type), &do_bigint_add); @@ -485,10 +487,10 @@ TF_BUILTIN(Add, AddStubAssembler) { BIND(&if_left_not_number); { Label if_left_bigint(this); - Node* left_instance_type = LoadMapInstanceType(left_map); + TNode<Uint16T> left_instance_type = LoadMapInstanceType(left_map); GotoIf(IsStringInstanceType(left_instance_type), &string_add_convert_right); - Node* right_instance_type = LoadMapInstanceType(right_map); + TNode<Uint16T> right_instance_type = LoadMapInstanceType(right_map); GotoIf(IsStringInstanceType(right_instance_type), &string_add_convert_left); GotoIf(IsBigIntInstanceType(left_instance_type), &if_left_bigint); @@ -525,15 +527,15 @@ TF_BUILTIN(Add, AddStubAssembler) { BIND(&string_add_convert_left); { // Convert {left} to a String and concatenate it with the String {right}. - TailCallBuiltin(Builtins::kStringAdd_ConvertLeft, context, var_left.value(), + TailCallBuiltin(Builtins::kStringAddConvertLeft, context, var_left.value(), var_right.value()); } BIND(&string_add_convert_right); { // Convert {right} to a String and concatenate it with the String {left}. - TailCallBuiltin(Builtins::kStringAdd_ConvertRight, context, - var_left.value(), var_right.value()); + TailCallBuiltin(Builtins::kStringAddConvertRight, context, var_left.value(), + var_right.value()); } BIND(&do_bigint_add); @@ -544,7 +546,8 @@ TF_BUILTIN(Add, AddStubAssembler) { BIND(&do_double_add); { - Node* value = Float64Add(var_left_double.value(), var_right_double.value()); + TNode<Float64T> value = + Float64Add(var_left_double.value(), var_right_double.value()); Return(AllocateHeapNumberWithValue(value)); } } @@ -696,7 +699,8 @@ TF_BUILTIN(Subtract, NumberBuiltinsAssembler) { BIND(&do_double_sub); { - Node* value = Float64Sub(var_left_double.value(), var_right_double.value()); + TNode<Float64T> value = + Float64Sub(var_left_double.value(), var_right_double.value()); Return(AllocateHeapNumberWithValue(value)); } @@ -780,7 +784,8 @@ TF_BUILTIN(Negate, NumberBuiltinsAssembler) { BIND(&do_double); { - Node* value = Float64Mul(var_input_double.value(), Float64Constant(-1)); + TNode<Float64T> value = + Float64Mul(var_input_double.value(), Float64Constant(-1)); Return(AllocateHeapNumberWithValue(value)); } @@ -807,7 +812,8 @@ TF_BUILTIN(Multiply, NumberBuiltinsAssembler) { Return(SmiMul(CAST(var_left.value()), CAST(var_right.value()))); BIND(&do_double_mul); - Node* value = Float64Mul(var_left_double.value(), var_right_double.value()); + TNode<Float64T> value = + Float64Mul(var_left_double.value(), var_right_double.value()); Return(AllocateHeapNumberWithValue(value)); BIND(&do_bigint_mul); @@ -851,8 +857,8 @@ TF_BUILTIN(Divide, NumberBuiltinsAssembler) { } BIND(÷nd_is_not_zero); - Node* untagged_divisor = SmiToInt32(divisor); - Node* untagged_dividend = SmiToInt32(dividend); + TNode<Int32T> untagged_divisor = SmiToInt32(divisor); + TNode<Int32T> untagged_dividend = SmiToInt32(dividend); // Do floating point division if {dividend} is kMinInt (or kMinInt - 1 // if the Smi size is 31) and {divisor} is -1. @@ -872,8 +878,9 @@ TF_BUILTIN(Divide, NumberBuiltinsAssembler) { // TODO(epertoso): consider adding a machine instruction that returns // both the result and the remainder. - Node* untagged_result = Int32Div(untagged_dividend, untagged_divisor); - Node* truncated = Int32Mul(untagged_result, untagged_divisor); + TNode<Int32T> untagged_result = + Int32Div(untagged_dividend, untagged_divisor); + TNode<Int32T> truncated = Int32Mul(untagged_result, untagged_divisor); // Do floating point division if the remainder is not 0. GotoIf(Word32NotEqual(untagged_dividend, truncated), &bailout); Return(SmiFromInt32(untagged_result)); @@ -890,7 +897,8 @@ TF_BUILTIN(Divide, NumberBuiltinsAssembler) { BIND(&do_double_div); { - Node* value = Float64Div(var_left_double.value(), var_right_double.value()); + TNode<Float64T> value = + Float64Div(var_left_double.value(), var_right_double.value()); Return(AllocateHeapNumberWithValue(value)); } @@ -916,7 +924,8 @@ TF_BUILTIN(Modulus, NumberBuiltinsAssembler) { Return(SmiMod(CAST(var_left.value()), CAST(var_right.value()))); BIND(&do_double_mod); - Node* value = Float64Mod(var_left_double.value(), var_right_double.value()); + TNode<Float64T> value = + Float64Mod(var_left_double.value(), var_right_double.value()); Return(AllocateHeapNumberWithValue(value)); BIND(&do_bigint_mod); diff --git a/deps/v8/src/builtins/builtins-object-gen.cc b/deps/v8/src/builtins/builtins-object-gen.cc index 8d59ee3bd1..db9d4ed657 100644 --- a/deps/v8/src/builtins/builtins-object-gen.cc +++ b/deps/v8/src/builtins/builtins-object-gen.cc @@ -11,6 +11,7 @@ #include "src/ic/accessor-assembler.h" #include "src/ic/keyed-store-generic.h" #include "src/objects/js-generator.h" +#include "src/objects/js-objects.h" #include "src/objects/property-descriptor-object.h" #include "src/objects/property-details.h" #include "src/objects/shared-function-info.h" @@ -44,10 +45,6 @@ class ObjectBuiltinsAssembler : public CodeStubAssembler { Node* ConstructDataDescriptor(Node* context, Node* value, Node* writable, Node* enumerable, Node* configurable); Node* GetAccessorOrUndefined(Node* accessor, Label* if_bailout); - - Node* IsSpecialReceiverMap(SloppyTNode<Map> map); - - TNode<Word32T> IsStringWrapperElementsKind(TNode<Map> map); }; class ObjectEntriesValuesBuiltinsAssembler : public ObjectBuiltinsAssembler { @@ -72,8 +69,6 @@ class ObjectEntriesValuesBuiltinsAssembler : public ObjectBuiltinsAssembler { void GetOwnValuesOrEntries(TNode<Context> context, TNode<Object> maybe_object, CollectType collect_type); - void GotoIfMapHasSlowProperties(TNode<Map> map, Label* if_slow); - TNode<JSArray> FastGetOwnValuesOrEntries( TNode<Context> context, TNode<JSObject> object, Label* if_call_runtime_with_fast_path, Label* if_no_properties, @@ -86,8 +81,8 @@ class ObjectEntriesValuesBuiltinsAssembler : public ObjectBuiltinsAssembler { void ObjectBuiltinsAssembler::ReturnToStringFormat(Node* context, Node* string) { - Node* lhs = StringConstant("[object "); - Node* rhs = StringConstant("]"); + TNode<String> lhs = StringConstant("[object "); + TNode<String> rhs = StringConstant("]"); Callable callable = CodeFactory::StringAdd(isolate(), STRING_ADD_CHECK_NONE); @@ -100,10 +95,10 @@ Node* ObjectBuiltinsAssembler::ConstructAccessorDescriptor(Node* context, Node* setter, Node* enumerable, Node* configurable) { - Node* native_context = LoadNativeContext(context); - Node* map = LoadContextElement( - native_context, Context::ACCESSOR_PROPERTY_DESCRIPTOR_MAP_INDEX); - Node* js_desc = AllocateJSObjectFromMap(map); + TNode<NativeContext> native_context = LoadNativeContext(context); + TNode<Map> map = CAST(LoadContextElement( + native_context, Context::ACCESSOR_PROPERTY_DESCRIPTOR_MAP_INDEX)); + TNode<JSObject> js_desc = AllocateJSObjectFromMap(map); StoreObjectFieldNoWriteBarrier( js_desc, JSAccessorPropertyDescriptor::kGetOffset, getter); @@ -124,10 +119,10 @@ Node* ObjectBuiltinsAssembler::ConstructDataDescriptor(Node* context, Node* writable, Node* enumerable, Node* configurable) { - Node* native_context = LoadNativeContext(context); - Node* map = LoadContextElement(native_context, - Context::DATA_PROPERTY_DESCRIPTOR_MAP_INDEX); - Node* js_desc = AllocateJSObjectFromMap(map); + TNode<NativeContext> native_context = LoadNativeContext(context); + TNode<Map> map = CAST(LoadContextElement( + native_context, Context::DATA_PROPERTY_DESCRIPTOR_MAP_INDEX)); + TNode<JSObject> js_desc = AllocateJSObjectFromMap(map); StoreObjectFieldNoWriteBarrier(js_desc, JSDataPropertyDescriptor::kValueOffset, value); @@ -144,28 +139,6 @@ Node* ObjectBuiltinsAssembler::ConstructDataDescriptor(Node* context, return js_desc; } -Node* ObjectBuiltinsAssembler::IsSpecialReceiverMap(SloppyTNode<Map> map) { - CSA_SLOW_ASSERT(this, IsMap(map)); - TNode<BoolT> is_special = - IsSpecialReceiverInstanceType(LoadMapInstanceType(map)); - uint32_t mask = - Map::HasNamedInterceptorBit::kMask | Map::IsAccessCheckNeededBit::kMask; - USE(mask); - // Interceptors or access checks imply special receiver. - CSA_ASSERT(this, - SelectConstant<BoolT>(IsSetWord32(LoadMapBitField(map), mask), - is_special, Int32TrueConstant())); - return is_special; -} - -TNode<Word32T> ObjectBuiltinsAssembler::IsStringWrapperElementsKind( - TNode<Map> map) { - Node* kind = LoadMapElementsKind(map); - return Word32Or( - Word32Equal(kind, Int32Constant(FAST_STRING_WRAPPER_ELEMENTS)), - Word32Equal(kind, Int32Constant(SLOW_STRING_WRAPPER_ELEMENTS))); -} - TNode<BoolT> ObjectEntriesValuesBuiltinsAssembler::IsPropertyEnumerable( TNode<Uint32T> details) { TNode<Uint32T> attributes = @@ -209,7 +182,7 @@ void ObjectEntriesValuesBuiltinsAssembler::GetOwnValuesOrEntries( BIND(&if_no_properties); { - Node* native_context = LoadNativeContext(context); + TNode<NativeContext> native_context = LoadNativeContext(context); TNode<Map> array_map = LoadJSArrayElementsMap(PACKED_ELEMENTS, native_context); TNode<JSArray> empty_array = AllocateJSArray( @@ -242,18 +215,11 @@ void ObjectEntriesValuesBuiltinsAssembler::GetOwnValuesOrEntries( } } -void ObjectEntriesValuesBuiltinsAssembler::GotoIfMapHasSlowProperties( - TNode<Map> map, Label* if_slow) { - GotoIf(IsStringWrapperElementsKind(map), if_slow); - GotoIf(IsSpecialReceiverMap(map), if_slow); - GotoIf(IsDictionaryMap(map), if_slow); -} - TNode<JSArray> ObjectEntriesValuesBuiltinsAssembler::FastGetOwnValuesOrEntries( TNode<Context> context, TNode<JSObject> object, Label* if_call_runtime_with_fast_path, Label* if_no_properties, CollectType collect_type) { - TNode<Context> native_context = LoadNativeContext(context); + TNode<NativeContext> native_context = LoadNativeContext(context); TNode<Map> array_map = LoadJSArrayElementsMap(PACKED_ELEMENTS, native_context); TNode<Map> map = LoadMap(object); @@ -308,9 +274,10 @@ TNode<JSArray> ObjectEntriesValuesBuiltinsAssembler::FastGetOwnValuesOrEntries( { // Currently, we will not invoke getters, // so, map will not be changed. - CSA_ASSERT(this, WordEqual(map, LoadMap(object))); + CSA_ASSERT(this, TaggedEqual(map, LoadMap(object))); TNode<IntPtrT> descriptor_entry = var_descriptor_number.value(); - Node* next_key = LoadKeyByDescriptorEntry(descriptors, descriptor_entry); + TNode<Name> next_key = + LoadKeyByDescriptorEntry(descriptors, descriptor_entry); // Skip Symbols. GotoIf(IsSymbol(next_key), &next_descriptor); @@ -378,7 +345,7 @@ ObjectEntriesValuesBuiltinsAssembler::FinalizeValuesOrEntriesJSArray( CSA_ASSERT(this, IsJSArrayMap(array_map)); GotoIf(IntPtrEqual(size, IntPtrConstant(0)), if_empty); - Node* array = AllocateJSArray(array_map, result, SmiTag(size)); + TNode<JSArray> array = AllocateJSArray(array_map, result, SmiTag(size)); return TNode<JSArray>::UncheckedCast(array); } @@ -412,8 +379,8 @@ TF_BUILTIN(ObjectPrototypeHasOwnProperty, ObjectBuiltinsAssembler) { Branch(TaggedIsSmi(object), &to_primitive, &if_objectisnotsmi); BIND(&if_objectisnotsmi); - Node* map = LoadMap(object); - TNode<Int32T> instance_type = LoadMapInstanceType(map); + TNode<Map> map = LoadMap(object); + TNode<Uint16T> instance_type = LoadMapInstanceType(map); { VARIABLE(var_index, MachineType::PointerRepresentation()); @@ -510,9 +477,9 @@ TF_BUILTIN(ObjectKeys, ObjectBuiltinsAssembler) { // Check if the {object} has a usable enum cache. GotoIf(TaggedIsSmi(object), &if_slow); - Node* object_map = LoadMap(object); - Node* object_bit_field3 = LoadMapBitField3(object_map); - Node* object_enum_length = + TNode<Map> object_map = LoadMap(object); + TNode<Uint32T> object_bit_field3 = LoadMapBitField3(object_map); + TNode<UintPtrT> object_enum_length = DecodeWordFromWord32<Map::EnumLengthBits>(object_bit_field3); GotoIf( WordEqual(object_enum_length, IntPtrConstant(kInvalidEnumCacheSentinel)), @@ -520,7 +487,7 @@ TF_BUILTIN(ObjectKeys, ObjectBuiltinsAssembler) { // Ensure that the {object} doesn't have any elements. CSA_ASSERT(this, IsJSObjectMap(object_map)); - Node* object_elements = LoadElements(object); + TNode<FixedArrayBase> object_elements = LoadElements(object); GotoIf(IsEmptyFixedArray(object_elements), &if_empty_elements); Branch(IsEmptySlowElementDictionary(object_elements), &if_empty_elements, &if_slow); @@ -532,19 +499,19 @@ TF_BUILTIN(ObjectKeys, ObjectBuiltinsAssembler) { BIND(&if_fast); { // The {object} has a usable enum cache, use that. - Node* object_descriptors = LoadMapDescriptors(object_map); - Node* object_enum_cache = - LoadObjectField(object_descriptors, DescriptorArray::kEnumCacheOffset); - Node* object_enum_keys = + TNode<DescriptorArray> object_descriptors = LoadMapDescriptors(object_map); + TNode<EnumCache> object_enum_cache = CAST( + LoadObjectField(object_descriptors, DescriptorArray::kEnumCacheOffset)); + TNode<Object> object_enum_keys = LoadObjectField(object_enum_cache, EnumCache::kKeysOffset); // Allocate a JSArray and copy the elements from the {object_enum_keys}. Node* array = nullptr; Node* elements = nullptr; - Node* native_context = LoadNativeContext(context); + TNode<NativeContext> native_context = LoadNativeContext(context); TNode<Map> array_map = LoadJSArrayElementsMap(PACKED_ELEMENTS, native_context); - TNode<Smi> array_length = SmiTag(object_enum_length); + TNode<Smi> array_length = SmiTag(Signed(object_enum_length)); std::tie(array, elements) = AllocateUninitializedJSArrayWithElements( PACKED_ELEMENTS, array_map, array_length, nullptr, object_enum_length, INTPTR_PARAMETERS); @@ -564,7 +531,8 @@ TF_BUILTIN(ObjectKeys, ObjectBuiltinsAssembler) { BIND(&if_slow); { // Let the runtime compute the elements. - Node* elements = CallRuntime(Runtime::kObjectKeys, context, object); + TNode<FixedArray> elements = + CAST(CallRuntime(Runtime::kObjectKeys, context, object)); var_length.Bind(LoadObjectField(elements, FixedArray::kLengthOffset)); var_elements.Bind(elements); Goto(&if_join); @@ -573,7 +541,7 @@ TF_BUILTIN(ObjectKeys, ObjectBuiltinsAssembler) { BIND(&if_join); { // Wrap the elements into a proper JSArray and return that. - Node* native_context = LoadNativeContext(context); + TNode<NativeContext> native_context = LoadNativeContext(context); TNode<Map> array_map = LoadJSArrayElementsMap(PACKED_ELEMENTS, native_context); TNode<JSArray> array = AllocateJSArray( @@ -596,25 +564,25 @@ TF_BUILTIN(ObjectGetOwnPropertyNames, ObjectBuiltinsAssembler) { // Take the slow path if the {object} IsCustomElementsReceiverInstanceType or // has any elements. GotoIf(TaggedIsSmi(object), &if_slow); - Node* object_map = LoadMap(object); - TNode<Int32T> instance_type = LoadMapInstanceType(object_map); + TNode<Map> object_map = LoadMap(object); + TNode<Uint16T> instance_type = LoadMapInstanceType(object_map); GotoIf(IsCustomElementsReceiverInstanceType(instance_type), &if_slow); - Node* object_elements = LoadElements(object); + TNode<FixedArrayBase> object_elements = LoadElements(object); GotoIf(IsEmptyFixedArray(object_elements), &if_empty_elements); Branch(IsEmptySlowElementDictionary(object_elements), &if_empty_elements, &if_slow); // Check if the {object} has a usable enum cache. BIND(&if_empty_elements); - Node* object_bit_field3 = LoadMapBitField3(object_map); - Node* object_enum_length = + TNode<Uint32T> object_bit_field3 = LoadMapBitField3(object_map); + TNode<UintPtrT> object_enum_length = DecodeWordFromWord32<Map::EnumLengthBits>(object_bit_field3); GotoIf( WordEqual(object_enum_length, IntPtrConstant(kInvalidEnumCacheSentinel)), &try_fast); // Check whether all own properties are enumerable. - Node* number_descriptors = + TNode<UintPtrT> number_descriptors = DecodeWordFromWord32<Map::NumberOfOwnDescriptorsBits>(object_bit_field3); GotoIfNot(WordEqual(object_enum_length, number_descriptors), &if_slow); @@ -625,19 +593,19 @@ TF_BUILTIN(ObjectGetOwnPropertyNames, ObjectBuiltinsAssembler) { { // The {object} has a usable enum cache and all own properties are // enumerable, use that. - Node* object_descriptors = LoadMapDescriptors(object_map); - Node* object_enum_cache = - LoadObjectField(object_descriptors, DescriptorArray::kEnumCacheOffset); - Node* object_enum_keys = + TNode<DescriptorArray> object_descriptors = LoadMapDescriptors(object_map); + TNode<EnumCache> object_enum_cache = CAST( + LoadObjectField(object_descriptors, DescriptorArray::kEnumCacheOffset)); + TNode<Object> object_enum_keys = LoadObjectField(object_enum_cache, EnumCache::kKeysOffset); // Allocate a JSArray and copy the elements from the {object_enum_keys}. Node* array = nullptr; Node* elements = nullptr; - Node* native_context = LoadNativeContext(context); + TNode<NativeContext> native_context = LoadNativeContext(context); TNode<Map> array_map = LoadJSArrayElementsMap(PACKED_ELEMENTS, native_context); - TNode<Smi> array_length = SmiTag(object_enum_length); + TNode<Smi> array_length = SmiTag(Signed(object_enum_length)); std::tie(array, elements) = AllocateUninitializedJSArrayWithElements( PACKED_ELEMENTS, array_map, array_length, nullptr, object_enum_length, INTPTR_PARAMETERS); @@ -649,8 +617,8 @@ TF_BUILTIN(ObjectGetOwnPropertyNames, ObjectBuiltinsAssembler) { BIND(&try_fast); { // Let the runtime compute the elements and try initializing enum cache. - Node* elements = CallRuntime(Runtime::kObjectGetOwnPropertyNamesTryFast, - context, object); + TNode<FixedArray> elements = CAST(CallRuntime( + Runtime::kObjectGetOwnPropertyNamesTryFast, context, object)); var_length.Bind(LoadObjectField(elements, FixedArray::kLengthOffset)); var_elements.Bind(elements); Goto(&if_join); @@ -667,8 +635,8 @@ TF_BUILTIN(ObjectGetOwnPropertyNames, ObjectBuiltinsAssembler) { BIND(&if_slow); { // Let the runtime compute the elements. - Node* elements = - CallRuntime(Runtime::kObjectGetOwnPropertyNames, context, object); + TNode<FixedArray> elements = + CAST(CallRuntime(Runtime::kObjectGetOwnPropertyNames, context, object)); var_length.Bind(LoadObjectField(elements, FixedArray::kLengthOffset)); var_elements.Bind(elements); Goto(&if_join); @@ -677,7 +645,7 @@ TF_BUILTIN(ObjectGetOwnPropertyNames, ObjectBuiltinsAssembler) { BIND(&if_join); { // Wrap the elements into a proper JSArray and return that. - Node* native_context = LoadNativeContext(context); + TNode<NativeContext> native_context = LoadNativeContext(context); TNode<Map> array_map = LoadJSArrayElementsMap(PACKED_ELEMENTS, native_context); TNode<JSArray> array = AllocateJSArray( @@ -770,8 +738,8 @@ TF_BUILTIN(ObjectToString, ObjectBuiltinsAssembler) { VARIABLE(var_default, MachineRepresentation::kTagged); VARIABLE(var_holder, MachineRepresentation::kTagged, receiver); GotoIf(TaggedIsSmi(receiver), &if_number); - Node* receiver_map = LoadMap(receiver); - Node* receiver_instance_type = LoadMapInstanceType(receiver_map); + TNode<Map> receiver_map = LoadMap(receiver); + TNode<Uint16T> receiver_instance_type = LoadMapInstanceType(receiver_map); GotoIf(IsPrimitiveInstanceType(receiver_instance_type), &if_primitive); const struct { InstanceType value; @@ -818,58 +786,58 @@ TF_BUILTIN(ObjectToString, ObjectBuiltinsAssembler) { BIND(&if_arguments); { - var_default.Bind(LoadRoot(RootIndex::karguments_to_string)); + var_default.Bind(ArgumentsToStringConstant()); Goto(&checkstringtag); } BIND(&if_array); { - var_default.Bind(LoadRoot(RootIndex::karray_to_string)); + var_default.Bind(ArrayToStringConstant()); Goto(&checkstringtag); } BIND(&if_boolean); { - Node* native_context = LoadNativeContext(context); - Node* boolean_constructor = - LoadContextElement(native_context, Context::BOOLEAN_FUNCTION_INDEX); - Node* boolean_initial_map = LoadObjectField( - boolean_constructor, JSFunction::kPrototypeOrInitialMapOffset); - Node* boolean_prototype = + TNode<NativeContext> native_context = LoadNativeContext(context); + TNode<JSFunction> boolean_constructor = CAST( + LoadContextElement(native_context, Context::BOOLEAN_FUNCTION_INDEX)); + TNode<Map> boolean_initial_map = CAST(LoadObjectField( + boolean_constructor, JSFunction::kPrototypeOrInitialMapOffset)); + TNode<Object> boolean_prototype = LoadObjectField(boolean_initial_map, Map::kPrototypeOffset); - var_default.Bind(LoadRoot(RootIndex::kboolean_to_string)); + var_default.Bind(BooleanToStringConstant()); var_holder.Bind(boolean_prototype); Goto(&checkstringtag); } BIND(&if_date); { - var_default.Bind(LoadRoot(RootIndex::kdate_to_string)); + var_default.Bind(DateToStringConstant()); Goto(&checkstringtag); } BIND(&if_error); { - var_default.Bind(LoadRoot(RootIndex::kerror_to_string)); + var_default.Bind(ErrorToStringConstant()); Goto(&checkstringtag); } BIND(&if_function); { - var_default.Bind(LoadRoot(RootIndex::kfunction_to_string)); + var_default.Bind(FunctionToStringConstant()); Goto(&checkstringtag); } BIND(&if_number); { - Node* native_context = LoadNativeContext(context); - Node* number_constructor = - LoadContextElement(native_context, Context::NUMBER_FUNCTION_INDEX); - Node* number_initial_map = LoadObjectField( - number_constructor, JSFunction::kPrototypeOrInitialMapOffset); - Node* number_prototype = + TNode<NativeContext> native_context = LoadNativeContext(context); + TNode<JSFunction> number_constructor = CAST( + LoadContextElement(native_context, Context::NUMBER_FUNCTION_INDEX)); + TNode<Map> number_initial_map = CAST(LoadObjectField( + number_constructor, JSFunction::kPrototypeOrInitialMapOffset)); + TNode<Object> number_prototype = LoadObjectField(number_initial_map, Map::kPrototypeOffset); - var_default.Bind(LoadRoot(RootIndex::knumber_to_string)); + var_default.Bind(NumberToStringConstant()); var_holder.Bind(number_prototype); Goto(&checkstringtag); } @@ -877,7 +845,7 @@ TF_BUILTIN(ObjectToString, ObjectBuiltinsAssembler) { BIND(&if_object); { CSA_ASSERT(this, IsJSReceiver(receiver)); - var_default.Bind(LoadRoot(RootIndex::kobject_to_string)); + var_default.Bind(ObjectToStringConstant()); Goto(&checkstringtag); } @@ -892,10 +860,10 @@ TF_BUILTIN(ObjectToString, ObjectBuiltinsAssembler) { GotoIf(IsSymbolMap(receiver_map), &if_symbol); GotoIf(IsUndefined(receiver), &return_undefined); CSA_ASSERT(this, IsNull(receiver)); - Return(LoadRoot(RootIndex::knull_to_string)); + Return(NullToStringConstant()); BIND(&return_undefined); - Return(LoadRoot(RootIndex::kundefined_to_string)); + Return(UndefinedToStringConstant()); } BIND(&if_proxy); @@ -905,16 +873,15 @@ TF_BUILTIN(ObjectToString, ObjectBuiltinsAssembler) { // depending on whether the {receiver} is callable. The order matters here, // i.e. we need to execute the %ArrayIsArray check before the [[Get]] below, // as the exception is observable. - Node* receiver_is_array = + TNode<Object> receiver_is_array = CallRuntime(Runtime::kArrayIsArray, context, receiver); TNode<String> builtin_tag = Select<String>( - IsTrue(receiver_is_array), - [=] { return CAST(LoadRoot(RootIndex::kArray_string)); }, + IsTrue(receiver_is_array), [=] { return ArrayStringConstant(); }, [=] { return Select<String>( IsCallableMap(receiver_map), - [=] { return CAST(LoadRoot(RootIndex::kFunction_string)); }, - [=] { return CAST(LoadRoot(RootIndex::kObject_string)); }); + [=] { return FunctionStringConstant(); }, + [=] { return ObjectStringConstant(); }); }); // Lookup the @@toStringTag property on the {receiver}. @@ -935,48 +902,48 @@ TF_BUILTIN(ObjectToString, ObjectBuiltinsAssembler) { BIND(&if_regexp); { - var_default.Bind(LoadRoot(RootIndex::kregexp_to_string)); + var_default.Bind(RegexpToStringConstant()); Goto(&checkstringtag); } BIND(&if_string); { - Node* native_context = LoadNativeContext(context); - Node* string_constructor = - LoadContextElement(native_context, Context::STRING_FUNCTION_INDEX); - Node* string_initial_map = LoadObjectField( - string_constructor, JSFunction::kPrototypeOrInitialMapOffset); - Node* string_prototype = + TNode<NativeContext> native_context = LoadNativeContext(context); + TNode<JSFunction> string_constructor = CAST( + LoadContextElement(native_context, Context::STRING_FUNCTION_INDEX)); + TNode<Map> string_initial_map = CAST(LoadObjectField( + string_constructor, JSFunction::kPrototypeOrInitialMapOffset)); + TNode<Object> string_prototype = LoadObjectField(string_initial_map, Map::kPrototypeOffset); - var_default.Bind(LoadRoot(RootIndex::kstring_to_string)); + var_default.Bind(StringToStringConstant()); var_holder.Bind(string_prototype); Goto(&checkstringtag); } BIND(&if_symbol); { - Node* native_context = LoadNativeContext(context); - Node* symbol_constructor = - LoadContextElement(native_context, Context::SYMBOL_FUNCTION_INDEX); - Node* symbol_initial_map = LoadObjectField( - symbol_constructor, JSFunction::kPrototypeOrInitialMapOffset); - Node* symbol_prototype = + TNode<NativeContext> native_context = LoadNativeContext(context); + TNode<JSFunction> symbol_constructor = CAST( + LoadContextElement(native_context, Context::SYMBOL_FUNCTION_INDEX)); + TNode<Map> symbol_initial_map = CAST(LoadObjectField( + symbol_constructor, JSFunction::kPrototypeOrInitialMapOffset)); + TNode<Object> symbol_prototype = LoadObjectField(symbol_initial_map, Map::kPrototypeOffset); - var_default.Bind(LoadRoot(RootIndex::kobject_to_string)); + var_default.Bind(ObjectToStringConstant()); var_holder.Bind(symbol_prototype); Goto(&checkstringtag); } BIND(&if_bigint); { - Node* native_context = LoadNativeContext(context); - Node* bigint_constructor = - LoadContextElement(native_context, Context::BIGINT_FUNCTION_INDEX); - Node* bigint_initial_map = LoadObjectField( - bigint_constructor, JSFunction::kPrototypeOrInitialMapOffset); - Node* bigint_prototype = + TNode<NativeContext> native_context = LoadNativeContext(context); + TNode<JSFunction> bigint_constructor = CAST( + LoadContextElement(native_context, Context::BIGINT_FUNCTION_INDEX)); + TNode<Map> bigint_initial_map = CAST(LoadObjectField( + bigint_constructor, JSFunction::kPrototypeOrInitialMapOffset)); + TNode<Object> bigint_prototype = LoadObjectField(bigint_initial_map, Map::kPrototypeOffset); - var_default.Bind(LoadRoot(RootIndex::kobject_to_string)); + var_default.Bind(ObjectToStringConstant()); var_holder.Bind(bigint_prototype); Goto(&checkstringtag); } @@ -994,11 +961,11 @@ TF_BUILTIN(ObjectToString, ObjectBuiltinsAssembler) { // which might have interesting properties. var_holder.Bind(receiver); GotoIf(TaggedIsSmi(receiver_value), &if_value_is_number); - Node* receiver_value_map = LoadMap(receiver_value); + TNode<Map> receiver_value_map = LoadMap(receiver_value); GotoIf(IsHeapNumberMap(receiver_value_map), &if_value_is_number); GotoIf(IsBooleanMap(receiver_value_map), &if_value_is_boolean); GotoIf(IsSymbolMap(receiver_value_map), &if_value_is_symbol); - Node* receiver_value_instance_type = + TNode<Uint16T> receiver_value_instance_type = LoadMapInstanceType(receiver_value_map); GotoIf(IsBigIntInstanceType(receiver_value_instance_type), &if_value_is_bigint); @@ -1007,31 +974,31 @@ TF_BUILTIN(ObjectToString, ObjectBuiltinsAssembler) { BIND(&if_value_is_number); { - var_default.Bind(LoadRoot(RootIndex::knumber_to_string)); + var_default.Bind(NumberToStringConstant()); Goto(&checkstringtag); } BIND(&if_value_is_boolean); { - var_default.Bind(LoadRoot(RootIndex::kboolean_to_string)); + var_default.Bind(BooleanToStringConstant()); Goto(&checkstringtag); } BIND(&if_value_is_string); { - var_default.Bind(LoadRoot(RootIndex::kstring_to_string)); + var_default.Bind(StringToStringConstant()); Goto(&checkstringtag); } BIND(&if_value_is_bigint); { - var_default.Bind(LoadRoot(RootIndex::kobject_to_string)); + var_default.Bind(ObjectToStringConstant()); Goto(&checkstringtag); } BIND(&if_value_is_symbol); { - var_default.Bind(LoadRoot(RootIndex::kobject_to_string)); + var_default.Bind(ObjectToStringConstant()); Goto(&checkstringtag); } } @@ -1048,8 +1015,8 @@ TF_BUILTIN(ObjectToString, ObjectBuiltinsAssembler) { { Node* holder = var_holder.value(); GotoIf(IsNull(holder), &return_default); - Node* holder_map = LoadMap(holder); - Node* holder_bit_field3 = LoadMapBitField3(holder_map); + TNode<Map> holder_map = LoadMap(holder); + TNode<Uint32T> holder_bit_field3 = LoadMapBitField3(holder_map); GotoIf(IsSetWord32<Map::MayHaveInterestingSymbolsBit>(holder_bit_field3), &return_generic); var_holder.Bind(LoadMapPrototype(holder_map)); @@ -1058,10 +1025,10 @@ TF_BUILTIN(ObjectToString, ObjectBuiltinsAssembler) { BIND(&return_generic); { - Node* tag = GetProperty(context, ToObject(context, receiver), - LoadRoot(RootIndex::kto_string_tag_symbol)); + TNode<Object> tag = GetProperty(context, ToObject(context, receiver), + ToStringTagSymbolConstant()); GotoIf(TaggedIsSmi(tag), &return_default); - GotoIfNot(IsString(tag), &return_default); + GotoIfNot(IsString(CAST(tag)), &return_default); ReturnToStringFormat(context, tag); } @@ -1080,9 +1047,9 @@ TF_BUILTIN(ObjectPrototypeValueOf, CodeStubAssembler) { // ES #sec-object.create TF_BUILTIN(CreateObjectWithoutProperties, ObjectBuiltinsAssembler) { - Node* const prototype = Parameter(Descriptor::kPrototypeArg); - Node* const context = Parameter(Descriptor::kContext); - Node* const native_context = LoadNativeContext(context); + TNode<Object> const prototype = CAST(Parameter(Descriptor::kPrototypeArg)); + TNode<Context> const context = CAST(Parameter(Descriptor::kContext)); + TNode<NativeContext> const native_context = LoadNativeContext(context); Label call_runtime(this, Label::kDeferred), prototype_null(this), prototype_jsreceiver(this); { @@ -1108,16 +1075,16 @@ TF_BUILTIN(CreateObjectWithoutProperties, ObjectBuiltinsAssembler) { { Comment("Prototype is JSReceiver"); properties.Bind(EmptyFixedArrayConstant()); - Node* object_function = - LoadContextElement(native_context, Context::OBJECT_FUNCTION_INDEX); - Node* object_function_map = LoadObjectField( + TNode<HeapObject> object_function = CAST( + LoadContextElement(native_context, Context::OBJECT_FUNCTION_INDEX)); + TNode<Object> object_function_map = LoadObjectField( object_function, JSFunction::kPrototypeOrInitialMapOffset); map.Bind(object_function_map); - GotoIf(WordEqual(prototype, LoadMapPrototype(map.value())), + GotoIf(TaggedEqual(prototype, LoadMapPrototype(map.value())), &instantiate_map); Comment("Try loading the prototype info"); - Node* prototype_info = - LoadMapPrototypeInfo(LoadMap(prototype), &call_runtime); + TNode<PrototypeInfo> prototype_info = + LoadMapPrototypeInfo(LoadMap(CAST(prototype)), &call_runtime); TNode<MaybeObject> maybe_map = LoadMaybeWeakObjectField( prototype_info, PrototypeInfo::kObjectCreateMapOffset); GotoIf(IsStrongReferenceTo(maybe_map, UndefinedConstant()), &call_runtime); @@ -1128,15 +1095,16 @@ TF_BUILTIN(CreateObjectWithoutProperties, ObjectBuiltinsAssembler) { BIND(&instantiate_map); { Comment("Instantiate map"); - Node* instance = AllocateJSObjectFromMap(map.value(), properties.value()); + TNode<JSObject> instance = + AllocateJSObjectFromMap(map.value(), properties.value()); Return(instance); } BIND(&call_runtime); { Comment("Call Runtime (prototype is not null/jsreceiver)"); - Node* result = CallRuntime(Runtime::kObjectCreate, context, prototype, - UndefinedConstant()); + TNode<Object> result = CallRuntime(Runtime::kObjectCreate, context, + prototype, UndefinedConstant()); Return(result); } } @@ -1146,13 +1114,13 @@ TF_BUILTIN(ObjectCreate, ObjectBuiltinsAssembler) { int const kPrototypeArg = 0; int const kPropertiesArg = 1; - Node* argc = + TNode<IntPtrT> argc = ChangeInt32ToIntPtr(Parameter(Descriptor::kJSActualArgumentsCount)); CodeStubArguments args(this, argc); - Node* prototype = args.GetOptionalArgumentValue(kPrototypeArg); - Node* properties = args.GetOptionalArgumentValue(kPropertiesArg); - Node* context = Parameter(Descriptor::kContext); + TNode<Object> prototype = args.GetOptionalArgumentValue(kPrototypeArg); + TNode<Object> properties = args.GetOptionalArgumentValue(kPropertiesArg); + TNode<Context> context = CAST(Parameter(Descriptor::kContext)); Label call_runtime(this, Label::kDeferred), prototype_valid(this), no_properties(this); @@ -1169,14 +1137,14 @@ TF_BUILTIN(ObjectCreate, ObjectBuiltinsAssembler) { GotoIf(TaggedIsSmi(properties), &call_runtime); // Undefined implies no properties. GotoIf(IsUndefined(properties), &no_properties); - Node* properties_map = LoadMap(properties); + TNode<Map> properties_map = LoadMap(CAST(properties)); GotoIf(IsSpecialReceiverMap(properties_map), &call_runtime); // Stay on the fast path only if there are no elements. - GotoIfNot(WordEqual(LoadElements(properties), - LoadRoot(RootIndex::kEmptyFixedArray)), - &call_runtime); + GotoIfNot( + TaggedEqual(LoadElements(CAST(properties)), EmptyFixedArrayConstant()), + &call_runtime); // Handle dictionary objects or fast objects with properties in runtime. - Node* bit_field3 = LoadMapBitField3(properties_map); + TNode<Uint32T> bit_field3 = LoadMapBitField3(properties_map); GotoIf(IsSetWord32<Map::IsDictionaryMapBit>(bit_field3), &call_runtime); Branch(IsSetWord32<Map::NumberOfOwnDescriptorsBits>(bit_field3), &call_runtime, &no_properties); @@ -1202,16 +1170,16 @@ TF_BUILTIN(ObjectCreate, ObjectBuiltinsAssembler) { BIND(&non_null_proto); { properties.Bind(EmptyFixedArrayConstant()); - Node* object_function = - LoadContextElement(context, Context::OBJECT_FUNCTION_INDEX); - Node* object_function_map = LoadObjectField( + TNode<HeapObject> object_function = + CAST(LoadContextElement(context, Context::OBJECT_FUNCTION_INDEX)); + TNode<Object> object_function_map = LoadObjectField( object_function, JSFunction::kPrototypeOrInitialMapOffset); map.Bind(object_function_map); - GotoIf(WordEqual(prototype, LoadMapPrototype(map.value())), + GotoIf(TaggedEqual(prototype, LoadMapPrototype(map.value())), &instantiate_map); // Try loading the prototype info. - Node* prototype_info = - LoadMapPrototypeInfo(LoadMap(prototype), &call_runtime); + TNode<PrototypeInfo> prototype_info = + LoadMapPrototypeInfo(LoadMap(CAST(prototype)), &call_runtime); Comment("Load ObjectCreateMap from PrototypeInfo"); TNode<MaybeObject> maybe_map = LoadMaybeWeakObjectField( prototype_info, PrototypeInfo::kObjectCreateMapOffset); @@ -1223,14 +1191,15 @@ TF_BUILTIN(ObjectCreate, ObjectBuiltinsAssembler) { BIND(&instantiate_map); { - Node* instance = AllocateJSObjectFromMap(map.value(), properties.value()); + TNode<JSObject> instance = + AllocateJSObjectFromMap(map.value(), properties.value()); args.PopAndReturn(instance); } } BIND(&call_runtime); { - Node* result = + TNode<Object> result = CallRuntime(Runtime::kObjectCreate, context, prototype, properties); args.PopAndReturn(result); } @@ -1256,11 +1225,11 @@ TF_BUILTIN(CreateIterResultObject, ObjectBuiltinsAssembler) { Node* const done = Parameter(Descriptor::kDone); Node* const context = Parameter(Descriptor::kContext); - Node* const native_context = LoadNativeContext(context); - Node* const map = - LoadContextElement(native_context, Context::ITERATOR_RESULT_MAP_INDEX); + TNode<NativeContext> const native_context = LoadNativeContext(context); + TNode<Map> const map = CAST( + LoadContextElement(native_context, Context::ITERATOR_RESULT_MAP_INDEX)); - Node* const result = AllocateJSObjectFromMap(map); + TNode<JSObject> const result = AllocateJSObjectFromMap(map); StoreObjectFieldNoWriteBarrier(result, JSIteratorResult::kValueOffset, value); StoreObjectFieldNoWriteBarrier(result, JSIteratorResult::kDoneOffset, done); @@ -1309,27 +1278,31 @@ TF_BUILTIN(CreateGeneratorObject, ObjectBuiltinsAssembler) { // have one. Label done(this), runtime(this); GotoIfNot(IsFunctionWithPrototypeSlotMap(LoadMap(closure)), &runtime); - Node* maybe_map = - LoadObjectField(closure, JSFunction::kPrototypeOrInitialMapOffset); + TNode<HeapObject> maybe_map = + CAST(LoadObjectField(closure, JSFunction::kPrototypeOrInitialMapOffset)); GotoIf(DoesntHaveInstanceType(maybe_map, MAP_TYPE), &runtime); + TNode<Map> map = CAST(maybe_map); - Node* shared = - LoadObjectField(closure, JSFunction::kSharedFunctionInfoOffset); - Node* bytecode_array = LoadSharedFunctionInfoBytecodeArray(shared); + TNode<SharedFunctionInfo> shared = + CAST(LoadObjectField(closure, JSFunction::kSharedFunctionInfoOffset)); + TNode<BytecodeArray> bytecode_array = + LoadSharedFunctionInfoBytecodeArray(shared); - Node* formal_parameter_count = ChangeInt32ToIntPtr( + TNode<IntPtrT> formal_parameter_count = ChangeInt32ToIntPtr( LoadObjectField(shared, SharedFunctionInfo::kFormalParameterCountOffset, MachineType::Uint16())); - Node* frame_size = ChangeInt32ToIntPtr(LoadObjectField( + TNode<IntPtrT> frame_size = ChangeInt32ToIntPtr(LoadObjectField( bytecode_array, BytecodeArray::kFrameSizeOffset, MachineType::Int32())); - Node* size = IntPtrAdd(WordSar(frame_size, IntPtrConstant(kTaggedSizeLog2)), - formal_parameter_count); - Node* parameters_and_registers = AllocateFixedArray(HOLEY_ELEMENTS, size); + TNode<WordT> size = + IntPtrAdd(WordSar(frame_size, IntPtrConstant(kTaggedSizeLog2)), + formal_parameter_count); + TNode<FixedArrayBase> parameters_and_registers = + AllocateFixedArray(HOLEY_ELEMENTS, size); FillFixedArrayWithValue(HOLEY_ELEMENTS, parameters_and_registers, IntPtrConstant(0), size, RootIndex::kUndefinedValue); // TODO(cbruni): support start_offset to avoid double initialization. - Node* result = AllocateJSObjectFromMap(maybe_map, nullptr, nullptr, kNone, - kWithSlackTracking); + TNode<JSObject> result = + AllocateJSObjectFromMap(map, nullptr, nullptr, kNone, kWithSlackTracking); StoreObjectFieldNoWriteBarrier(result, JSGeneratorObject::kFunctionOffset, closure); StoreObjectFieldNoWriteBarrier(result, JSGeneratorObject::kContextOffset, @@ -1339,13 +1312,13 @@ TF_BUILTIN(CreateGeneratorObject, ObjectBuiltinsAssembler) { StoreObjectFieldNoWriteBarrier( result, JSGeneratorObject::kParametersAndRegistersOffset, parameters_and_registers); - Node* resume_mode = SmiConstant(JSGeneratorObject::ResumeMode::kNext); + TNode<Smi> resume_mode = SmiConstant(JSGeneratorObject::ResumeMode::kNext); StoreObjectFieldNoWriteBarrier(result, JSGeneratorObject::kResumeModeOffset, resume_mode); - Node* executing = SmiConstant(JSGeneratorObject::kGeneratorExecuting); + TNode<Smi> executing = SmiConstant(JSGeneratorObject::kGeneratorExecuting); StoreObjectFieldNoWriteBarrier(result, JSGeneratorObject::kContinuationOffset, executing); - GotoIfNot(InstanceTypeEqual(LoadMapInstanceType(maybe_map), + GotoIfNot(InstanceTypeEqual(LoadMapInstanceType(map), JS_ASYNC_GENERATOR_OBJECT_TYPE), &done); StoreObjectFieldNoWriteBarrier( @@ -1369,11 +1342,11 @@ TF_BUILTIN(ObjectGetOwnPropertyDescriptor, ObjectBuiltinsAssembler) { CSA_ASSERT(this, IsUndefined(Parameter(Descriptor::kJSNewTarget))); CodeStubArguments args(this, ChangeInt32ToIntPtr(argc)); - Node* object = args.GetOptionalArgumentValue(0); - Node* key = args.GetOptionalArgumentValue(1); + TNode<Object> object_input = args.GetOptionalArgumentValue(0); + TNode<Object> key = args.GetOptionalArgumentValue(1); // 1. Let obj be ? ToObject(O). - object = ToObject_Inline(CAST(context), CAST(object)); + TNode<JSReceiver> object = ToObject_Inline(CAST(context), object_input); // 2. Let key be ? ToPropertyKey(P). key = CallBuiltin(Builtins::kToName, context, key); @@ -1382,8 +1355,8 @@ TF_BUILTIN(ObjectGetOwnPropertyDescriptor, ObjectBuiltinsAssembler) { Label if_keyisindex(this), if_iskeyunique(this), call_runtime(this, Label::kDeferred), return_undefined(this, Label::kDeferred), if_notunique_name(this); - Node* map = LoadMap(object); - TNode<Int32T> instance_type = LoadMapInstanceType(map); + TNode<Map> map = LoadMap(object); + TNode<Uint16T> instance_type = LoadMapInstanceType(map); GotoIf(IsSpecialReceiverInstanceType(instance_type), &call_runtime); { VARIABLE(var_index, MachineType::PointerRepresentation(), @@ -1440,15 +1413,15 @@ TF_BUILTIN(ObjectGetOwnPropertyDescriptor, ObjectBuiltinsAssembler) { BIND(&call_runtime); { - Node* desc = + TNode<Object> desc = CallRuntime(Runtime::kGetOwnPropertyDescriptor, context, object, key); GotoIf(IsUndefined(desc), &return_undefined); - CSA_ASSERT(this, IsFixedArray(desc)); + TNode<FixedArray> desc_array = CAST(desc); // 4. Return FromPropertyDescriptor(desc). - Node* js_desc = FromPropertyDescriptor(context, desc); + Node* js_desc = FromPropertyDescriptor(context, desc_array); args.PopAndReturn(js_desc); } BIND(&return_undefined); @@ -1471,10 +1444,10 @@ Node* ObjectBuiltinsAssembler::FromPropertyDescriptor(Node* context, Node* desc) { VARIABLE(js_descriptor, MachineRepresentation::kTagged); - Node* flags = LoadAndUntagToWord32ObjectField( + TNode<Int32T> flags = LoadAndUntagToWord32ObjectField( desc, PropertyDescriptorObject::kFlagsOffset); - Node* has_flags = + TNode<Word32T> has_flags = Word32And(flags, Int32Constant(PropertyDescriptorObject::kHasMask)); Label if_accessor_desc(this), if_data_desc(this), if_generic_desc(this), @@ -1512,13 +1485,13 @@ Node* ObjectBuiltinsAssembler::FromPropertyDescriptor(Node* context, BIND(&if_generic_desc); { - Node* native_context = LoadNativeContext(context); - Node* map = LoadContextElement( - native_context, Context::SLOW_OBJECT_WITH_OBJECT_PROTOTYPE_MAP); + TNode<NativeContext> native_context = LoadNativeContext(context); + TNode<Map> map = CAST(LoadContextElement( + native_context, Context::SLOW_OBJECT_WITH_OBJECT_PROTOTYPE_MAP)); // We want to preallocate the slots for value, writable, get, set, // enumerable and configurable - a total of 6 TNode<NameDictionary> properties = AllocateNameDictionary(6); - Node* js_desc = AllocateJSObjectFromMap(map, properties); + TNode<JSObject> js_desc = AllocateJSObjectFromMap(map, properties); Label bailout(this, Label::kDeferred); @@ -1579,8 +1552,10 @@ Node* ObjectBuiltinsAssembler::FromPropertyDetails(Node* context, BIND(&if_accessor_desc); { - Node* getter = LoadObjectField(raw_value, AccessorPair::kGetterOffset); - Node* setter = LoadObjectField(raw_value, AccessorPair::kSetterOffset); + TNode<Object> getter = + LoadObjectField(raw_value, AccessorPair::kGetterOffset); + TNode<Object> setter = + LoadObjectField(raw_value, AccessorPair::kSetterOffset); js_descriptor.Bind(ConstructAccessorDescriptor( context, GetAccessorOrUndefined(getter, if_bailout), GetAccessorOrUndefined(setter, if_bailout), @@ -1610,7 +1585,7 @@ Node* ObjectBuiltinsAssembler::GetAccessorOrUndefined(Node* accessor, GotoIf(IsNull(accessor), &bind_undefined); result.Bind(accessor); - Node* map = LoadMap(accessor); + TNode<Map> map = LoadMap(accessor); // TODO(ishell): probe template instantiations cache. GotoIf(IsFunctionTemplateInfoMap(map), if_bailout); Goto(&return_result); diff --git a/deps/v8/src/builtins/builtins-object.cc b/deps/v8/src/builtins/builtins-object.cc index 1ca5fffd8d..93f011ffa1 100644 --- a/deps/v8/src/builtins/builtins-object.cc +++ b/deps/v8/src/builtins/builtins-object.cc @@ -156,8 +156,11 @@ Object ObjectLookupAccessor(Isolate* isolate, Handle<Object> object, case LookupIterator::ACCESSOR: { Handle<Object> maybe_pair = it.GetAccessors(); if (maybe_pair->IsAccessorPair()) { + Handle<NativeContext> native_context = + it.GetHolder<JSReceiver>()->GetCreationContext(); return *AccessorPair::GetComponent( - isolate, Handle<AccessorPair>::cast(maybe_pair), component); + isolate, native_context, Handle<AccessorPair>::cast(maybe_pair), + component); } } } diff --git a/deps/v8/src/builtins/builtins-promise-gen.cc b/deps/v8/src/builtins/builtins-promise-gen.cc index 1339e2dccd..a1da55e0d9 100644 --- a/deps/v8/src/builtins/builtins-promise-gen.cc +++ b/deps/v8/src/builtins/builtins-promise-gen.cc @@ -11,6 +11,8 @@ #include "src/builtins/builtins.h" #include "src/codegen/code-factory.h" #include "src/codegen/code-stub-assembler.h" +#include "src/objects/fixed-array.h" +#include "src/objects/js-objects.h" #include "src/objects/js-promise.h" #include "src/objects/objects-inl.h" #include "src/objects/smi.h" @@ -24,13 +26,14 @@ using TNode = CodeStubAssembler::TNode<T>; using IteratorRecord = TorqueStructIteratorRecord; Node* PromiseBuiltinsAssembler::AllocateJSPromise(Node* context) { - Node* const native_context = LoadNativeContext(context); - Node* const promise_fun = - LoadContextElement(native_context, Context::PROMISE_FUNCTION_INDEX); + TNode<NativeContext> const native_context = LoadNativeContext(context); + TNode<JSFunction> const promise_fun = + CAST(LoadContextElement(native_context, Context::PROMISE_FUNCTION_INDEX)); CSA_ASSERT(this, IsFunctionWithPrototypeSlotMap(LoadMap(promise_fun))); - Node* const promise_map = + TNode<Object> const promise_map = LoadObjectField(promise_fun, JSFunction::kPrototypeOrInitialMapOffset); - Node* const promise = Allocate(JSPromise::kSizeWithEmbedderFields); + TNode<HeapObject> const promise = + Allocate(JSPromise::kSizeWithEmbedderFields); StoreMapNoWriteBarrier(promise, promise_map); StoreObjectFieldRoot(promise, JSPromise::kPropertiesOrHashOffset, RootIndex::kEmptyFixedArray); @@ -99,14 +102,14 @@ PromiseBuiltinsAssembler::CreatePromiseResolvingFunctions( Node* promise, Node* debug_event, Node* native_context) { Node* const promise_context = CreatePromiseResolvingFunctionsContext( promise, debug_event, native_context); - Node* const map = LoadContextElement( + TNode<Object> const map = LoadContextElement( native_context, Context::STRICT_FUNCTION_WITHOUT_PROTOTYPE_MAP_INDEX); - Node* const resolve_info = LoadContextElement( + TNode<Object> const resolve_info = LoadContextElement( native_context, Context::PROMISE_CAPABILITY_DEFAULT_RESOLVE_SHARED_FUN_INDEX); Node* const resolve = AllocateFunctionWithMapAndContext(map, resolve_info, promise_context); - Node* const reject_info = LoadContextElement( + TNode<Object> const reject_info = LoadContextElement( native_context, Context::PROMISE_CAPABILITY_DEFAULT_REJECT_SHARED_FUN_INDEX); Node* const reject = @@ -137,7 +140,7 @@ void PromiseBuiltinsAssembler::ExtractHandlerContext(Node* handler, }; static_assert(arraysize(case_values) == arraysize(case_labels), ""); TNode<Map> handler_map = LoadMap(var_handler.value()); - TNode<Int32T> handler_type = LoadMapInstanceType(handler_map); + TNode<Uint16T> handler_type = LoadMapInstanceType(handler_map); Switch(handler_type, &done, case_values, case_labels, arraysize(case_labels)); @@ -162,7 +165,7 @@ void PromiseBuiltinsAssembler::ExtractHandlerContext(Node* handler, BIND(&if_function); { // Use the function's context. - Node* handler_context = + TNode<Object> handler_context = LoadObjectField(var_handler.value(), JSFunction::kContextOffset); var_context->Bind(LoadNativeContext(CAST(handler_context))); Goto(&done); @@ -176,19 +179,19 @@ void PromiseBuiltinsAssembler::ExtractHandlerContext(Node* handler, // ES #sec-newpromisecapability TF_BUILTIN(NewPromiseCapability, PromiseBuiltinsAssembler) { - Node* const context = Parameter(Descriptor::kContext); - Node* const constructor = Parameter(Descriptor::kConstructor); - Node* const debug_event = Parameter(Descriptor::kDebugEvent); - TNode<Context> const native_context = LoadNativeContext(context); + TNode<Context> const context = CAST(Parameter(Descriptor::kContext)); + TNode<Object> const constructor = CAST(Parameter(Descriptor::kConstructor)); + TNode<Object> const debug_event = CAST(Parameter(Descriptor::kDebugEvent)); + TNode<NativeContext> const native_context = LoadNativeContext(context); Label if_not_constructor(this, Label::kDeferred), if_notcallable(this, Label::kDeferred), if_fast_promise_capability(this), if_slow_promise_capability(this, Label::kDeferred); GotoIf(TaggedIsSmi(constructor), &if_not_constructor); - GotoIfNot(IsConstructorMap(LoadMap(constructor)), &if_not_constructor); - Branch(WordEqual(constructor, - LoadContextElement(native_context, - Context::PROMISE_FUNCTION_INDEX)), + GotoIfNot(IsConstructorMap(LoadMap(CAST(constructor))), &if_not_constructor); + Branch(TaggedEqual(constructor, + LoadContextElement(native_context, + Context::PROMISE_FUNCTION_INDEX)), &if_fast_promise_capability, &if_slow_promise_capability); BIND(&if_fast_promise_capability); @@ -201,7 +204,7 @@ TF_BUILTIN(NewPromiseCapability, PromiseBuiltinsAssembler) { std::tie(resolve, reject) = CreatePromiseResolvingFunctions(promise, debug_event, native_context); - Node* capability = Allocate(PromiseCapability::kSize); + TNode<HeapObject> capability = Allocate(PromiseCapability::kSize); StoreMapNoWriteBarrier(capability, RootIndex::kPromiseCapabilityMap); StoreObjectFieldNoWriteBarrier(capability, PromiseCapability::kPromiseOffset, promise); @@ -214,7 +217,7 @@ TF_BUILTIN(NewPromiseCapability, PromiseBuiltinsAssembler) { BIND(&if_slow_promise_capability); { - Node* capability = Allocate(PromiseCapability::kSize); + TNode<HeapObject> capability = Allocate(PromiseCapability::kSize); StoreMapNoWriteBarrier(capability, RootIndex::kPromiseCapabilityMap); StoreObjectFieldRoot(capability, PromiseCapability::kPromiseOffset, RootIndex::kUndefinedValue); @@ -225,25 +228,26 @@ TF_BUILTIN(NewPromiseCapability, PromiseBuiltinsAssembler) { Node* executor_context = CreatePromiseGetCapabilitiesExecutorContext(capability, native_context); - Node* executor_info = LoadContextElement( + TNode<Object> executor_info = LoadContextElement( native_context, Context::PROMISE_GET_CAPABILITIES_EXECUTOR_SHARED_FUN); - Node* function_map = LoadContextElement( + TNode<Object> function_map = LoadContextElement( native_context, Context::STRICT_FUNCTION_WITHOUT_PROTOTYPE_MAP_INDEX); TNode<JSFunction> executor = CAST(AllocateFunctionWithMapAndContext( function_map, executor_info, executor_context)); - Node* promise = Construct(native_context, CAST(constructor), executor); + TNode<JSReceiver> promise = + Construct(native_context, CAST(constructor), executor); StoreObjectField(capability, PromiseCapability::kPromiseOffset, promise); - Node* resolve = + TNode<Object> resolve = LoadObjectField(capability, PromiseCapability::kResolveOffset); GotoIf(TaggedIsSmi(resolve), &if_notcallable); - GotoIfNot(IsCallable(resolve), &if_notcallable); + GotoIfNot(IsCallable(CAST(resolve)), &if_notcallable); - Node* reject = + TNode<Object> reject = LoadObjectField(capability, PromiseCapability::kRejectOffset); GotoIf(TaggedIsSmi(reject), &if_notcallable); - GotoIfNot(IsCallable(reject), &if_notcallable); + GotoIfNot(IsCallable(CAST(reject)), &if_notcallable); Return(capability); } @@ -258,7 +262,8 @@ Node* PromiseBuiltinsAssembler::CreatePromiseContext(Node* native_context, int slots) { DCHECK_GE(slots, Context::MIN_CONTEXT_SLOTS); - Node* const context = AllocateInNewSpace(FixedArray::SizeFor(slots)); + TNode<HeapObject> const context = + AllocateInNewSpace(FixedArray::SizeFor(slots)); InitializeFunctionContext(native_context, context, slots); return context; } @@ -296,9 +301,10 @@ PromiseBuiltinsAssembler::CreatePromiseAllResolveElementFunction( index, SmiConstant(PropertyArray::HashField::kMax))); CSA_ASSERT(this, IsNativeContext(native_context)); - Node* const map = LoadContextElement( + TNode<Object> const map = LoadContextElement( native_context, Context::STRICT_FUNCTION_WITHOUT_PROTOTYPE_MAP_INDEX); - Node* const resolve_info = LoadContextElement(native_context, slot_index); + TNode<Object> const resolve_info = + LoadContextElement(native_context, slot_index); TNode<JSFunction> resolve = Cast(AllocateFunctionWithMapAndContext(map, resolve_info, context)); @@ -332,7 +338,8 @@ Node* PromiseBuiltinsAssembler::CreatePromiseGetCapabilitiesExecutorContext( } Node* PromiseBuiltinsAssembler::PromiseHasHandler(Node* promise) { - Node* const flags = LoadObjectField(promise, JSPromise::kFlagsOffset); + TNode<Smi> const flags = + CAST(LoadObjectField(promise, JSPromise::kFlagsOffset)); return IsSetWord(SmiUntag(flags), 1 << JSPromise::kHasHandlerBit); } @@ -344,12 +351,12 @@ void PromiseBuiltinsAssembler::PromiseSetHasHandler(Node* promise) { StoreObjectFieldNoWriteBarrier(promise, JSPromise::kFlagsOffset, new_flags); } -Node* PromiseBuiltinsAssembler::IsPromiseStatus( - Node* actual, v8::Promise::PromiseState expected) { +TNode<BoolT> PromiseBuiltinsAssembler::IsPromiseStatus( + TNode<Word32T> actual, v8::Promise::PromiseState expected) { return Word32Equal(actual, Int32Constant(expected)); } -Node* PromiseBuiltinsAssembler::PromiseStatus(Node* promise) { +TNode<Word32T> PromiseBuiltinsAssembler::PromiseStatus(Node* promise) { STATIC_ASSERT(JSPromise::kStatusShift == 0); TNode<Smi> const flags = CAST(LoadObjectField(promise, JSPromise::kFlagsOffset)); @@ -394,7 +401,7 @@ void PromiseBuiltinsAssembler::PerformPromiseThen( IsUndefined(result_promise_or_capability))); Label if_pending(this), if_notpending(this), done(this); - Node* const status = PromiseStatus(promise); + TNode<Word32T> const status = PromiseStatus(promise); Branch(IsPromiseStatus(status, v8::Promise::kPending), &if_pending, &if_notpending); @@ -404,7 +411,7 @@ void PromiseBuiltinsAssembler::PerformPromiseThen( // PromiseReaction holding both the onFulfilled and onRejected callbacks. // Once the {promise} is resolved we decide on the concrete handler to // push onto the microtask queue. - Node* const promise_reactions = + TNode<Object> const promise_reactions = LoadObjectField(promise, JSPromise::kReactionsOrResultOffset); Node* const reaction = AllocatePromiseReaction(promise_reactions, result_promise_or_capability, @@ -426,7 +433,7 @@ void PromiseBuiltinsAssembler::PerformPromiseThen( BIND(&if_fulfilled); { - var_map.Bind(LoadRoot(RootIndex::kPromiseFulfillReactionJobTaskMap)); + var_map.Bind(PromiseFulfillReactionJobTaskMapConstant()); var_handler.Bind(on_fulfilled); Label use_fallback(this, Label::kDeferred), done(this); @@ -445,7 +452,7 @@ void PromiseBuiltinsAssembler::PerformPromiseThen( BIND(&if_rejected); { CSA_ASSERT(this, IsPromiseStatus(status, v8::Promise::kRejected)); - var_map.Bind(LoadRoot(RootIndex::kPromiseRejectReactionJobTaskMap)); + var_map.Bind(PromiseRejectReactionJobTaskMapConstant()); var_handler.Bind(on_rejected); Label use_fallback(this, Label::kDeferred), done(this); @@ -465,7 +472,7 @@ void PromiseBuiltinsAssembler::PerformPromiseThen( BIND(&enqueue); { - Node* argument = + TNode<Object> argument = LoadObjectField(promise, JSPromise::kReactionsOrResultOffset); Node* microtask = AllocatePromiseReactionJobTask( var_map.value(), var_handler_context.value(), argument, @@ -500,7 +507,7 @@ TF_BUILTIN(PerformPromiseThen, PromiseBuiltinsAssembler) { Node* PromiseBuiltinsAssembler::AllocatePromiseReaction( Node* next, Node* promise_or_capability, Node* fulfill_handler, Node* reject_handler) { - Node* const reaction = Allocate(PromiseReaction::kSize); + TNode<HeapObject> const reaction = Allocate(PromiseReaction::kSize); StoreMapNoWriteBarrier(reaction, RootIndex::kPromiseReactionMap); StoreObjectFieldNoWriteBarrier(reaction, PromiseReaction::kNextOffset, next); StoreObjectFieldNoWriteBarrier(reaction, @@ -516,7 +523,7 @@ Node* PromiseBuiltinsAssembler::AllocatePromiseReaction( Node* PromiseBuiltinsAssembler::AllocatePromiseReactionJobTask( Node* map, Node* context, Node* argument, Node* handler, Node* promise_or_capability) { - Node* const microtask = + TNode<HeapObject> const microtask = Allocate(PromiseReactionJobTask::kSizeOfAllPromiseReactionJobTasks); StoreMapNoWriteBarrier(microtask, map); StoreObjectFieldNoWriteBarrier( @@ -531,19 +538,10 @@ Node* PromiseBuiltinsAssembler::AllocatePromiseReactionJobTask( return microtask; } -Node* PromiseBuiltinsAssembler::AllocatePromiseReactionJobTask( - RootIndex map_root_index, Node* context, Node* argument, Node* handler, - Node* promise_or_capability) { - DCHECK(map_root_index == RootIndex::kPromiseFulfillReactionJobTaskMap || - map_root_index == RootIndex::kPromiseRejectReactionJobTaskMap); - Node* const map = LoadRoot(map_root_index); - return AllocatePromiseReactionJobTask(map, context, argument, handler, - promise_or_capability); -} - Node* PromiseBuiltinsAssembler::AllocatePromiseResolveThenableJobTask( Node* promise_to_resolve, Node* then, Node* thenable, Node* context) { - Node* const microtask = Allocate(PromiseResolveThenableJobTask::kSize); + TNode<HeapObject> const microtask = + Allocate(PromiseResolveThenableJobTask::kSize); StoreMapNoWriteBarrier(microtask, RootIndex::kPromiseResolveThenableJobTaskMap); StoreObjectFieldNoWriteBarrier( @@ -574,8 +572,7 @@ Node* PromiseBuiltinsAssembler::TriggerPromiseReactions( // PromiseReaction instances and not actual JavaScript values (which // would indicate that we're rejecting or resolving an already settled // promise), see https://crbug.com/931640 for details on this. - TNode<Map> promise_reaction_map = - CAST(LoadRoot(RootIndex::kPromiseReactionMap)); + TNode<Map> promise_reaction_map = PromiseReactionMapConstant(); Label loop(this, {&var_current, &var_reversed}), done_loop(this); Goto(&loop); @@ -583,7 +580,8 @@ Node* PromiseBuiltinsAssembler::TriggerPromiseReactions( { Node* current = var_current.value(); GotoIf(TaggedIsSmi(current), &done_loop); - CSA_CHECK(this, WordEqual(LoadMap(CAST(current)), promise_reaction_map)); + CSA_CHECK(this, + TaggedEqual(LoadMap(CAST(current)), promise_reaction_map)); var_current.Bind(LoadObjectField(current, PromiseReaction::kNextOffset)); StoreObjectField(current, PromiseReaction::kNextOffset, var_reversed.value()); @@ -690,7 +688,7 @@ Node* PromiseBuiltinsAssembler::InvokeThen(Node* native_context, Node* receiver, VARIABLE(var_result, MachineRepresentation::kTagged); Label if_fast(this), if_slow(this, Label::kDeferred), done(this, &var_result); GotoIf(TaggedIsSmi(receiver), &if_slow); - Node* const receiver_map = LoadMap(receiver); + TNode<Map> const receiver_map = LoadMap(receiver); // We can skip the "then" lookup on {receiver} if it's [[Prototype]] // is the (initial) Promise.prototype and the Promise#then protector // is intact, as that guards the lookup path for the "then" property @@ -700,7 +698,7 @@ Node* PromiseBuiltinsAssembler::InvokeThen(Node* native_context, Node* receiver, BIND(&if_fast); { - Node* const then = + TNode<Object> const then = LoadContextElement(native_context, Context::PROMISE_THEN_INDEX); Node* const result = CallJS(CodeFactory::CallFunction( @@ -712,8 +710,8 @@ Node* PromiseBuiltinsAssembler::InvokeThen(Node* native_context, Node* receiver, BIND(&if_slow); { - Node* const then = GetProperty(native_context, receiver, - isolate()->factory()->then_string()); + TNode<Object> const then = GetProperty(native_context, receiver, + isolate()->factory()->then_string()); Node* const result = CallJS( CodeFactory::Call(isolate(), ConvertReceiverMode::kNotNullOrUndefined), native_context, then, receiver, args...); @@ -740,8 +738,8 @@ Node* PromiseBuiltinsAssembler::CallResolve(Node* native_context, BIND(&if_fast); { - Node* const result = CallBuiltin(Builtins::kPromiseResolve, native_context, - constructor, value); + TNode<Object> const result = CallBuiltin( + Builtins::kPromiseResolve, native_context, constructor, value); GotoIfException(result, if_exception, var_exception); var_result.Bind(result); @@ -766,18 +764,19 @@ Node* PromiseBuiltinsAssembler::CallResolve(Node* native_context, } void PromiseBuiltinsAssembler::BranchIfPromiseResolveLookupChainIntact( - Node* native_context, Node* constructor, Label* if_fast, Label* if_slow) { + Node* native_context, SloppyTNode<Object> constructor, Label* if_fast, + Label* if_slow) { CSA_ASSERT(this, IsNativeContext(native_context)); GotoIfForceSlowPath(if_slow); - Node* const promise_fun = + TNode<Object> promise_fun = LoadContextElement(native_context, Context::PROMISE_FUNCTION_INDEX); - GotoIfNot(WordEqual(promise_fun, constructor), if_slow); + GotoIfNot(TaggedEqual(promise_fun, constructor), if_slow); Branch(IsPromiseResolveProtectorCellInvalid(), if_slow, if_fast); } void PromiseBuiltinsAssembler::GotoIfNotPromiseResolveLookupChainIntact( - Node* native_context, Node* constructor, Label* if_slow) { + Node* native_context, SloppyTNode<Object> constructor, Label* if_slow) { Label if_fast(this); BranchIfPromiseResolveLookupChainIntact(native_context, constructor, &if_fast, if_slow); @@ -789,10 +788,10 @@ void PromiseBuiltinsAssembler::BranchIfPromiseSpeciesLookupChainIntact( CSA_ASSERT(this, IsNativeContext(native_context)); CSA_ASSERT(this, IsJSPromiseMap(promise_map)); - Node* const promise_prototype = + TNode<Object> promise_prototype = LoadContextElement(native_context, Context::PROMISE_PROTOTYPE_INDEX); GotoIfForceSlowPath(if_slow); - GotoIfNot(WordEqual(LoadMapPrototype(promise_map), promise_prototype), + GotoIfNot(TaggedEqual(LoadMapPrototype(promise_map), promise_prototype), if_slow); Branch(IsPromiseSpeciesProtectorCellInvalid(), if_slow, if_fast); } @@ -804,16 +803,16 @@ void PromiseBuiltinsAssembler::BranchIfPromiseThenLookupChainIntact( GotoIfForceSlowPath(if_slow); GotoIfNot(IsJSPromiseMap(receiver_map), if_slow); - Node* const promise_prototype = + TNode<Object> const promise_prototype = LoadContextElement(native_context, Context::PROMISE_PROTOTYPE_INDEX); - GotoIfNot(WordEqual(LoadMapPrototype(receiver_map), promise_prototype), + GotoIfNot(TaggedEqual(LoadMapPrototype(receiver_map), promise_prototype), if_slow); Branch(IsPromiseThenProtectorCellInvalid(), if_slow, if_fast); } void PromiseBuiltinsAssembler::BranchIfAccessCheckFailed( - Node* context, Node* native_context, Node* promise_constructor, - Node* executor, Label* if_noaccess) { + SloppyTNode<Context> context, SloppyTNode<Context> native_context, + Node* promise_constructor, Node* executor, Label* if_noaccess) { VARIABLE(var_executor, MachineRepresentation::kTagged); var_executor.Bind(executor); Label has_access(this), call_runtime(this, Label::kDeferred); @@ -824,7 +823,7 @@ void PromiseBuiltinsAssembler::BranchIfAccessCheckFailed( Goto(&loop_over_bound_function); BIND(&loop_over_bound_function); { - Node* executor_type = LoadInstanceType(var_executor.value()); + TNode<Uint16T> executor_type = LoadInstanceType(var_executor.value()); GotoIf(InstanceTypeEqual(executor_type, JS_FUNCTION_TYPE), &found_function); GotoIfNot(InstanceTypeEqual(executor_type, JS_BOUND_FUNCTION_TYPE), &call_runtime); @@ -838,18 +837,19 @@ void PromiseBuiltinsAssembler::BranchIfAccessCheckFailed( // out to the runtime. BIND(&found_function); { - Node* function_context = - LoadObjectField(var_executor.value(), JSFunction::kContextOffset); - Node* native_function_context = LoadNativeContext(function_context); - Branch(WordEqual(native_context, native_function_context), &has_access, + TNode<Context> function_context = + CAST(LoadObjectField(var_executor.value(), JSFunction::kContextOffset)); + TNode<NativeContext> native_function_context = + LoadNativeContext(function_context); + Branch(TaggedEqual(native_context, native_function_context), &has_access, &call_runtime); } BIND(&call_runtime); { - Branch(WordEqual(CallRuntime(Runtime::kAllowDynamicFunction, context, - promise_constructor), - TrueConstant()), + Branch(TaggedEqual(CallRuntime(Runtime::kAllowDynamicFunction, context, + promise_constructor), + TrueConstant()), &has_access, if_noaccess); } @@ -888,12 +888,12 @@ TF_BUILTIN(PromiseCapabilityDefaultReject, PromiseBuiltinsAssembler) { Node* const context = Parameter(Descriptor::kContext); // 2. Let promise be F.[[Promise]]. - Node* const promise = + TNode<Object> const promise = LoadContextElement(context, PromiseBuiltins::kPromiseSlot); // 3. Let alreadyResolved be F.[[AlreadyResolved]]. Label if_already_resolved(this, Label::kDeferred); - Node* const already_resolved = + TNode<Object> const already_resolved = LoadContextElement(context, PromiseBuiltins::kAlreadyResolvedSlot); // 4. If alreadyResolved.[[Value]] is true, return undefined. @@ -904,7 +904,7 @@ TF_BUILTIN(PromiseCapabilityDefaultReject, PromiseBuiltinsAssembler) { context, PromiseBuiltins::kAlreadyResolvedSlot, TrueConstant()); // 6. Return RejectPromise(promise, reason). - Node* const debug_event = + TNode<Object> const debug_event = LoadContextElement(context, PromiseBuiltins::kDebugEventSlot); Return(CallBuiltin(Builtins::kRejectPromise, context, promise, reason, debug_event)); @@ -922,12 +922,12 @@ TF_BUILTIN(PromiseCapabilityDefaultResolve, PromiseBuiltinsAssembler) { Node* const context = Parameter(Descriptor::kContext); // 2. Let promise be F.[[Promise]]. - Node* const promise = + TNode<Object> const promise = LoadContextElement(context, PromiseBuiltins::kPromiseSlot); // 3. Let alreadyResolved be F.[[AlreadyResolved]]. Label if_already_resolved(this, Label::kDeferred); - Node* const already_resolved = + TNode<Object> const already_resolved = LoadContextElement(context, PromiseBuiltins::kAlreadyResolvedSlot); // 4. If alreadyResolved.[[Value]] is true, return undefined. @@ -967,9 +967,9 @@ TF_BUILTIN(PromiseConstructorLazyDeoptContinuation, PromiseBuiltinsAssembler) { // ES6 #sec-promise-executor TF_BUILTIN(PromiseConstructor, PromiseBuiltinsAssembler) { - Node* const executor = Parameter(Descriptor::kExecutor); - Node* const new_target = Parameter(Descriptor::kJSNewTarget); - Node* const context = Parameter(Descriptor::kContext); + TNode<Object> executor = CAST(Parameter(Descriptor::kExecutor)); + TNode<Object> new_target = CAST(Parameter(Descriptor::kJSNewTarget)); + TNode<Context> context = CAST(Parameter(Descriptor::kContext)); Isolate* isolate = this->isolate(); Label if_targetisundefined(this, Label::kDeferred); @@ -980,12 +980,12 @@ TF_BUILTIN(PromiseConstructor, PromiseBuiltinsAssembler) { GotoIf(TaggedIsSmi(executor), &if_notcallable); - Node* const executor_map = LoadMap(executor); + TNode<Map> const executor_map = LoadMap(CAST(executor)); GotoIfNot(IsCallableMap(executor_map), &if_notcallable); - Node* const native_context = LoadNativeContext(context); - Node* const promise_fun = - LoadContextElement(native_context, Context::PROMISE_FUNCTION_INDEX); + TNode<NativeContext> const native_context = LoadNativeContext(context); + TNode<JSFunction> const promise_fun = + CAST(LoadContextElement(native_context, Context::PROMISE_FUNCTION_INDEX)); Node* const is_debug_active = IsDebugActive(); Label if_targetisnotmodified(this), if_targetismodified(this, Label::kDeferred), run_executor(this), @@ -994,7 +994,7 @@ TF_BUILTIN(PromiseConstructor, PromiseBuiltinsAssembler) { BranchIfAccessCheckFailed(context, native_context, promise_fun, executor, &if_noaccess); - Branch(WordEqual(promise_fun, new_target), &if_targetisnotmodified, + Branch(TaggedEqual(promise_fun, new_target), &if_targetisnotmodified, &if_targetismodified); VARIABLE(var_result, MachineRepresentation::kTagged); @@ -1011,8 +1011,8 @@ TF_BUILTIN(PromiseConstructor, PromiseBuiltinsAssembler) { BIND(&if_targetismodified); { ConstructorBuiltinsAssembler constructor_assembler(this->state()); - Node* const instance = constructor_assembler.EmitFastNewObject( - context, promise_fun, new_target); + TNode<JSObject> instance = constructor_assembler.EmitFastNewObject( + context, promise_fun, CAST(new_target)); PromiseInit(instance); var_result.Bind(instance); @@ -1071,7 +1071,7 @@ TF_BUILTIN(PromiseConstructor, PromiseBuiltinsAssembler) { // Silently fail if the stack looks fishy. BIND(&if_noaccess); { - Node* const counter_id = + TNode<Smi> const counter_id = SmiConstant(v8::Isolate::kPromiseConstructorReturnedUndefined); CallRuntime(Runtime::kIncrementUseCounter, context, counter_id); Return(UndefinedConstant()); @@ -1139,17 +1139,17 @@ TF_BUILTIN(PromisePrototypeThen, PromiseBuiltinsAssembler) { // 3. Let C be ? SpeciesConstructor(promise, %Promise%). Label fast_promise_capability(this), slow_constructor(this, Label::kDeferred), slow_promise_capability(this, Label::kDeferred); - Node* const native_context = LoadNativeContext(context); - Node* const promise_fun = - LoadContextElement(native_context, Context::PROMISE_FUNCTION_INDEX); - Node* const promise_map = LoadMap(promise); + TNode<NativeContext> const native_context = LoadNativeContext(context); + TNode<JSFunction> promise_fun = + CAST(LoadContextElement(native_context, Context::PROMISE_FUNCTION_INDEX)); + TNode<Map> const promise_map = LoadMap(promise); BranchIfPromiseSpeciesLookupChainIntact( native_context, promise_map, &fast_promise_capability, &slow_constructor); BIND(&slow_constructor); - Node* const constructor = + TNode<JSReceiver> constructor = SpeciesConstructor(native_context, promise, promise_fun); - Branch(WordEqual(constructor, promise_fun), &fast_promise_capability, + Branch(TaggedEqual(constructor, promise_fun), &fast_promise_capability, &slow_promise_capability); // 4. Let resultCapability be ? NewPromiseCapability(C). @@ -1167,9 +1167,9 @@ TF_BUILTIN(PromisePrototypeThen, PromiseBuiltinsAssembler) { BIND(&slow_promise_capability); { - Node* const debug_event = TrueConstant(); - Node* const capability = CallBuiltin(Builtins::kNewPromiseCapability, - context, constructor, debug_event); + TNode<Oddball> const debug_event = TrueConstant(); + TNode<PromiseCapability> const capability = CAST(CallBuiltin( + Builtins::kNewPromiseCapability, context, constructor, debug_event)); var_result_promise.Bind( LoadObjectField(capability, PromiseCapability::kPromiseOffset)); var_result_promise_or_capability.Bind(capability); @@ -1221,26 +1221,22 @@ TF_BUILTIN(PromisePrototypeThen, PromiseBuiltinsAssembler) { TF_BUILTIN(PromisePrototypeCatch, PromiseBuiltinsAssembler) { // 1. Let promise be the this value. Node* const receiver = Parameter(Descriptor::kReceiver); - Node* const on_fulfilled = UndefinedConstant(); + TNode<Oddball> const on_fulfilled = UndefinedConstant(); Node* const on_rejected = Parameter(Descriptor::kOnRejected); Node* const context = Parameter(Descriptor::kContext); // 2. Return ? Invoke(promise, "then", « undefined, onRejected »). - Node* const native_context = LoadNativeContext(context); + TNode<NativeContext> const native_context = LoadNativeContext(context); Return(InvokeThen(native_context, receiver, on_fulfilled, on_rejected)); } // ES #sec-promiseresolvethenablejob TF_BUILTIN(PromiseResolveThenableJob, PromiseBuiltinsAssembler) { - Node* const native_context = Parameter(Descriptor::kContext); - Node* const promise_to_resolve = Parameter(Descriptor::kPromiseToResolve); - Node* const thenable = Parameter(Descriptor::kThenable); - Node* const then = Parameter(Descriptor::kThen); - - CSA_ASSERT(this, TaggedIsNotSmi(thenable)); - CSA_ASSERT(this, IsJSReceiver(thenable)); - CSA_ASSERT(this, IsJSPromise(promise_to_resolve)); - CSA_ASSERT(this, IsNativeContext(native_context)); + TNode<NativeContext> native_context = CAST(Parameter(Descriptor::kContext)); + TNode<JSPromise> promise_to_resolve = + CAST(Parameter(Descriptor::kPromiseToResolve)); + TNode<JSReceiver> thenable = CAST(Parameter(Descriptor::kThenable)); + TNode<Object> then = CAST(Parameter(Descriptor::kThen)); // We can use a simple optimization here if we know that {then} is the initial // Promise.prototype.then method, and {thenable} is a JSPromise whose @@ -1251,10 +1247,10 @@ TF_BUILTIN(PromiseResolveThenableJob, PromiseBuiltinsAssembler) { // We take the generic (slow-)path if a PromiseHook is enabled or the debugger // is active, to make sure we expose spec compliant behavior. Label if_fast(this), if_slow(this, Label::kDeferred); - Node* const promise_then = + TNode<Object> promise_then = LoadContextElement(native_context, Context::PROMISE_THEN_INDEX); - GotoIfNot(WordEqual(then, promise_then), &if_slow); - Node* const thenable_map = LoadMap(thenable); + GotoIfNot(TaggedEqual(then, promise_then), &if_slow); + TNode<Map> const thenable_map = LoadMap(thenable); GotoIfNot(IsJSPromiseMap(thenable_map), &if_slow); GotoIf(IsPromiseHookEnabledOrDebugIsActiveOrHasAsyncEventDelegate(), &if_slow); @@ -1379,8 +1375,8 @@ void PromiseBuiltinsAssembler::PromiseReactionJob(Node* context, Node* argument, { // In the general case we need to call the (user provided) // promiseCapability.[[Resolve]] function. - Node* const resolve = LoadObjectField(promise_or_capability, - PromiseCapability::kResolveOffset); + TNode<Object> const resolve = LoadObjectField( + promise_or_capability, PromiseCapability::kResolveOffset); Node* const result = CallJS( CodeFactory::Call(isolate(), ConvertReceiverMode::kNullOrUndefined), context, resolve, UndefinedConstant(), value); @@ -1412,8 +1408,8 @@ void PromiseBuiltinsAssembler::PromiseReactionJob(Node* context, Node* argument, Label if_exception(this, Label::kDeferred); VARIABLE(var_exception, MachineRepresentation::kTagged, TheHoleConstant()); - Node* const reject = LoadObjectField(promise_or_capability, - PromiseCapability::kRejectOffset); + TNode<Object> const reject = LoadObjectField( + promise_or_capability, PromiseCapability::kRejectOffset); Node* const result = CallJS( CodeFactory::Call(isolate(), ConvertReceiverMode::kNullOrUndefined), context, reject, UndefinedConstant(), reason); @@ -1463,64 +1459,63 @@ TF_BUILTIN(PromiseResolveTrampoline, PromiseBuiltinsAssembler) { // 1. Let C be the this value. Node* receiver = Parameter(Descriptor::kReceiver); Node* value = Parameter(Descriptor::kValue); - Node* context = Parameter(Descriptor::kContext); + TNode<Context> context = CAST(Parameter(Descriptor::kContext)); // 2. If Type(C) is not Object, throw a TypeError exception. - ThrowIfNotJSReceiver(context, receiver, MessageTemplate::kCalledOnNonObject, - "PromiseResolve"); + ThrowIfNotJSReceiver(context, CAST(receiver), + MessageTemplate::kCalledOnNonObject, "PromiseResolve"); // 3. Return ? PromiseResolve(C, x). Return(CallBuiltin(Builtins::kPromiseResolve, context, receiver, value)); } TF_BUILTIN(PromiseResolve, PromiseBuiltinsAssembler) { - Node* constructor = Parameter(Descriptor::kConstructor); - Node* value = Parameter(Descriptor::kValue); - Node* context = Parameter(Descriptor::kContext); - - CSA_ASSERT(this, IsJSReceiver(constructor)); + TNode<JSReceiver> constructor = CAST(Parameter(Descriptor::kConstructor)); + TNode<Object> value = CAST(Parameter(Descriptor::kValue)); + TNode<Context> context = CAST(Parameter(Descriptor::kContext)); - Node* const native_context = LoadNativeContext(context); - Node* const promise_fun = - LoadContextElement(native_context, Context::PROMISE_FUNCTION_INDEX); + TNode<NativeContext> native_context = LoadNativeContext(context); + TNode<JSFunction> promise_fun = + CAST(LoadContextElement(native_context, Context::PROMISE_FUNCTION_INDEX)); Label if_slow_constructor(this, Label::kDeferred), if_need_to_allocate(this); // Check if {value} is a JSPromise. GotoIf(TaggedIsSmi(value), &if_need_to_allocate); - Node* const value_map = LoadMap(value); + TNode<Map> const value_map = LoadMap(CAST(value)); GotoIfNot(IsJSPromiseMap(value_map), &if_need_to_allocate); // We can skip the "constructor" lookup on {value} if it's [[Prototype]] // is the (initial) Promise.prototype and the @@species protector is // intact, as that guards the lookup path for "constructor" on // JSPromise instances which have the (initial) Promise.prototype. - Node* const promise_prototype = + TNode<Object> promise_prototype = LoadContextElement(native_context, Context::PROMISE_PROTOTYPE_INDEX); - GotoIfNot(WordEqual(LoadMapPrototype(value_map), promise_prototype), + GotoIfNot(TaggedEqual(LoadMapPrototype(value_map), promise_prototype), &if_slow_constructor); GotoIf(IsPromiseSpeciesProtectorCellInvalid(), &if_slow_constructor); // If the {constructor} is the Promise function, we just immediately // return the {value} here and don't bother wrapping it into a // native Promise. - GotoIfNot(WordEqual(promise_fun, constructor), &if_slow_constructor); + GotoIfNot(TaggedEqual(promise_fun, constructor), &if_slow_constructor); Return(value); // At this point, value or/and constructor are not native promises, but // they could be of the same subclass. BIND(&if_slow_constructor); { - Node* const value_constructor = + TNode<Object> value_constructor = GetProperty(context, value, isolate()->factory()->constructor_string()); - GotoIfNot(WordEqual(value_constructor, constructor), &if_need_to_allocate); + GotoIfNot(TaggedEqual(value_constructor, constructor), + &if_need_to_allocate); Return(value); } BIND(&if_need_to_allocate); { Label if_nativepromise(this), if_notnativepromise(this, Label::kDeferred); - Branch(WordEqual(promise_fun, constructor), &if_nativepromise, + Branch(TaggedEqual(promise_fun, constructor), &if_nativepromise, &if_notnativepromise); // This adds a fast path for native promises that don't need to @@ -1534,17 +1529,17 @@ TF_BUILTIN(PromiseResolve, PromiseBuiltinsAssembler) { BIND(&if_notnativepromise); { - Node* const debug_event = TrueConstant(); - Node* const capability = CallBuiltin(Builtins::kNewPromiseCapability, - context, constructor, debug_event); + TNode<Oddball> const debug_event = TrueConstant(); + TNode<PromiseCapability> const capability = CAST(CallBuiltin( + Builtins::kNewPromiseCapability, context, constructor, debug_event)); - Node* const resolve = + TNode<Object> const resolve = LoadObjectField(capability, PromiseCapability::kResolveOffset); CallJS( CodeFactory::Call(isolate(), ConvertReceiverMode::kNullOrUndefined), context, resolve, UndefinedConstant(), value); - Node* const result = + TNode<Object> const result = LoadObjectField(capability, PromiseCapability::kPromiseOffset); Return(result); } @@ -1557,8 +1552,8 @@ TF_BUILTIN(PromiseGetCapabilitiesExecutor, PromiseBuiltinsAssembler) { Node* const reject = Parameter(Descriptor::kReject); Node* const context = Parameter(Descriptor::kContext); - Node* const capability = - LoadContextElement(context, PromiseBuiltins::kCapabilitySlot); + TNode<PromiseCapability> const capability = + CAST(LoadContextElement(context, PromiseBuiltins::kCapabilitySlot)); Label if_alreadyinvoked(this, Label::kDeferred); GotoIfNot(IsUndefined( @@ -1579,20 +1574,20 @@ TF_BUILTIN(PromiseGetCapabilitiesExecutor, PromiseBuiltinsAssembler) { TF_BUILTIN(PromiseReject, PromiseBuiltinsAssembler) { // 1. Let C be the this value. - Node* const receiver = Parameter(Descriptor::kReceiver); - Node* const reason = Parameter(Descriptor::kReason); - Node* const context = Parameter(Descriptor::kContext); + TNode<Object> receiver = CAST(Parameter(Descriptor::kReceiver)); + TNode<Object> reason = CAST(Parameter(Descriptor::kReason)); + TNode<Context> context = CAST(Parameter(Descriptor::kContext)); // 2. If Type(C) is not Object, throw a TypeError exception. ThrowIfNotJSReceiver(context, receiver, MessageTemplate::kCalledOnNonObject, "PromiseReject"); Label if_nativepromise(this), if_custompromise(this, Label::kDeferred); - Node* const native_context = LoadNativeContext(context); + TNode<NativeContext> const native_context = LoadNativeContext(context); - Node* const promise_fun = + TNode<Object> promise_fun = LoadContextElement(native_context, Context::PROMISE_FUNCTION_INDEX); - Branch(WordEqual(promise_fun, receiver), &if_nativepromise, + Branch(TaggedEqual(promise_fun, receiver), &if_nativepromise, &if_custompromise); BIND(&if_nativepromise); @@ -1607,18 +1602,18 @@ TF_BUILTIN(PromiseReject, PromiseBuiltinsAssembler) { BIND(&if_custompromise); { // 3. Let promiseCapability be ? NewPromiseCapability(C). - Node* const debug_event = TrueConstant(); - Node* const capability = CallBuiltin(Builtins::kNewPromiseCapability, - context, receiver, debug_event); + TNode<Oddball> const debug_event = TrueConstant(); + TNode<PromiseCapability> const capability = CAST(CallBuiltin( + Builtins::kNewPromiseCapability, context, receiver, debug_event)); // 4. Perform ? Call(promiseCapability.[[Reject]], undefined, « r »). - Node* const reject = + TNode<Object> const reject = LoadObjectField(capability, PromiseCapability::kRejectOffset); CallJS(CodeFactory::Call(isolate(), ConvertReceiverMode::kNullOrUndefined), context, reject, UndefinedConstant(), reason); // 5. Return promiseCapability.[[Promise]]. - Node* const promise = + TNode<Object> const promise = LoadObjectField(capability, PromiseCapability::kPromiseOffset); Return(promise); } @@ -1632,13 +1627,13 @@ std::pair<Node*, Node*> PromiseBuiltinsAssembler::CreatePromiseFinallyFunctions( promise_context, PromiseBuiltins::kOnFinallySlot, on_finally); StoreContextElementNoWriteBarrier( promise_context, PromiseBuiltins::kConstructorSlot, constructor); - Node* const map = LoadContextElement( + TNode<Object> const map = LoadContextElement( native_context, Context::STRICT_FUNCTION_WITHOUT_PROTOTYPE_MAP_INDEX); - Node* const then_finally_info = LoadContextElement( + TNode<Object> const then_finally_info = LoadContextElement( native_context, Context::PROMISE_THEN_FINALLY_SHARED_FUN); Node* const then_finally = AllocateFunctionWithMapAndContext( map, then_finally_info, promise_context); - Node* const catch_finally_info = LoadContextElement( + TNode<Object> const catch_finally_info = LoadContextElement( native_context, Context::PROMISE_CATCH_FINALLY_SHARED_FUN); Node* const catch_finally = AllocateFunctionWithMapAndContext( map, catch_finally_info, promise_context); @@ -1648,7 +1643,8 @@ std::pair<Node*, Node*> PromiseBuiltinsAssembler::CreatePromiseFinallyFunctions( TF_BUILTIN(PromiseValueThunkFinally, PromiseBuiltinsAssembler) { Node* const context = Parameter(Descriptor::kContext); - Node* const value = LoadContextElement(context, PromiseBuiltins::kValueSlot); + TNode<Object> const value = + LoadContextElement(context, PromiseBuiltins::kValueSlot); Return(value); } @@ -1658,9 +1654,9 @@ Node* PromiseBuiltinsAssembler::CreateValueThunkFunction(Node* value, native_context, PromiseBuiltins::kPromiseValueThunkOrReasonContextLength); StoreContextElementNoWriteBarrier(value_thunk_context, PromiseBuiltins::kValueSlot, value); - Node* const map = LoadContextElement( + TNode<Object> const map = LoadContextElement( native_context, Context::STRICT_FUNCTION_WITHOUT_PROTOTYPE_MAP_INDEX); - Node* const value_thunk_info = LoadContextElement( + TNode<Object> const value_thunk_info = LoadContextElement( native_context, Context::PROMISE_VALUE_THUNK_FINALLY_SHARED_FUN); Node* const value_thunk = AllocateFunctionWithMapAndContext( map, value_thunk_info, value_thunk_context); @@ -1674,8 +1670,8 @@ TF_BUILTIN(PromiseThenFinally, PromiseBuiltinsAssembler) { Node* const context = Parameter(Descriptor::kContext); // 1. Let onFinally be F.[[OnFinally]]. - Node* const on_finally = - LoadContextElement(context, PromiseBuiltins::kOnFinallySlot); + TNode<HeapObject> const on_finally = + CAST(LoadContextElement(context, PromiseBuiltins::kOnFinallySlot)); // 2. Assert: IsCallable(onFinally) is true. CSA_ASSERT(this, IsCallable(on_finally)); @@ -1686,18 +1682,18 @@ TF_BUILTIN(PromiseThenFinally, PromiseBuiltinsAssembler) { context, on_finally, UndefinedConstant()); // 4. Let C be F.[[Constructor]]. - Node* const constructor = - LoadContextElement(context, PromiseBuiltins::kConstructorSlot); + TNode<JSFunction> const constructor = + CAST(LoadContextElement(context, PromiseBuiltins::kConstructorSlot)); // 5. Assert: IsConstructor(C) is true. CSA_ASSERT(this, IsConstructor(constructor)); // 6. Let promise be ? PromiseResolve(C, result). - Node* const promise = - CallBuiltin(Builtins::kPromiseResolve, context, constructor, result); + TNode<Object> const promise = + CallBuiltin(Builtins::kPromiseResolve, context, constructor, result); // 7. Let valueThunk be equivalent to a function that returns value. - Node* const native_context = LoadNativeContext(context); + TNode<NativeContext> const native_context = LoadNativeContext(context); Node* const value_thunk = CreateValueThunkFunction(value, native_context); // 8. Return ? Invoke(promise, "then", « valueThunk »). @@ -1707,7 +1703,8 @@ TF_BUILTIN(PromiseThenFinally, PromiseBuiltinsAssembler) { TF_BUILTIN(PromiseThrowerFinally, PromiseBuiltinsAssembler) { Node* const context = Parameter(Descriptor::kContext); - Node* const reason = LoadContextElement(context, PromiseBuiltins::kValueSlot); + TNode<Object> const reason = + LoadContextElement(context, PromiseBuiltins::kValueSlot); CallRuntime(Runtime::kThrow, context, reason); Unreachable(); } @@ -1718,9 +1715,9 @@ Node* PromiseBuiltinsAssembler::CreateThrowerFunction(Node* reason, native_context, PromiseBuiltins::kPromiseValueThunkOrReasonContextLength); StoreContextElementNoWriteBarrier(thrower_context, PromiseBuiltins::kValueSlot, reason); - Node* const map = LoadContextElement( + TNode<Object> const map = LoadContextElement( native_context, Context::STRICT_FUNCTION_WITHOUT_PROTOTYPE_MAP_INDEX); - Node* const thrower_info = LoadContextElement( + TNode<Object> const thrower_info = LoadContextElement( native_context, Context::PROMISE_THROWER_FINALLY_SHARED_FUN); Node* const thrower = AllocateFunctionWithMapAndContext(map, thrower_info, thrower_context); @@ -1734,8 +1731,8 @@ TF_BUILTIN(PromiseCatchFinally, PromiseBuiltinsAssembler) { Node* const context = Parameter(Descriptor::kContext); // 1. Let onFinally be F.[[OnFinally]]. - Node* const on_finally = - LoadContextElement(context, PromiseBuiltins::kOnFinallySlot); + TNode<HeapObject> const on_finally = + CAST(LoadContextElement(context, PromiseBuiltins::kOnFinallySlot)); // 2. Assert: IsCallable(onFinally) is true. CSA_ASSERT(this, IsCallable(on_finally)); @@ -1746,18 +1743,18 @@ TF_BUILTIN(PromiseCatchFinally, PromiseBuiltinsAssembler) { context, on_finally, UndefinedConstant()); // 4. Let C be F.[[Constructor]]. - Node* const constructor = - LoadContextElement(context, PromiseBuiltins::kConstructorSlot); + TNode<JSFunction> const constructor = + CAST(LoadContextElement(context, PromiseBuiltins::kConstructorSlot)); // 5. Assert: IsConstructor(C) is true. CSA_ASSERT(this, IsConstructor(constructor)); // 6. Let promise be ? PromiseResolve(C, result). - Node* const promise = - CallBuiltin(Builtins::kPromiseResolve, context, constructor, result); + TNode<Object> const promise = + CallBuiltin(Builtins::kPromiseResolve, context, constructor, result); // 7. Let thrower be equivalent to a function that throws reason. - Node* const native_context = LoadNativeContext(context); + TNode<NativeContext> const native_context = LoadNativeContext(context); Node* const thrower = CreateThrowerFunction(reason, native_context); // 8. Return ? Invoke(promise, "then", « thrower »). @@ -1770,26 +1767,27 @@ TF_BUILTIN(PromisePrototypeFinally, PromiseBuiltinsAssembler) { // 1. Let promise be the this value. Node* const receiver = Parameter(Descriptor::kReceiver); Node* const on_finally = Parameter(Descriptor::kOnFinally); - Node* const context = Parameter(Descriptor::kContext); + TNode<Context> context = CAST(Parameter(Descriptor::kContext)); // 2. If Type(promise) is not Object, throw a TypeError exception. - ThrowIfNotJSReceiver(context, receiver, MessageTemplate::kCalledOnNonObject, + ThrowIfNotJSReceiver(context, CAST(receiver), + MessageTemplate::kCalledOnNonObject, "Promise.prototype.finally"); // 3. Let C be ? SpeciesConstructor(promise, %Promise%). - Node* const native_context = LoadNativeContext(context); - Node* const promise_fun = + TNode<NativeContext> const native_context = LoadNativeContext(context); + TNode<Object> const promise_fun = LoadContextElement(native_context, Context::PROMISE_FUNCTION_INDEX); VARIABLE(var_constructor, MachineRepresentation::kTagged, promise_fun); Label slow_constructor(this, Label::kDeferred), done_constructor(this); - Node* const receiver_map = LoadMap(receiver); + TNode<Map> const receiver_map = LoadMap(receiver); GotoIfNot(IsJSPromiseMap(receiver_map), &slow_constructor); BranchIfPromiseSpeciesLookupChainIntact(native_context, receiver_map, &done_constructor, &slow_constructor); BIND(&slow_constructor); { - Node* const constructor = - SpeciesConstructor(context, receiver, promise_fun); + TNode<JSReceiver> const constructor = + SpeciesConstructor(context, receiver, CAST(promise_fun)); var_constructor.Bind(constructor); Goto(&done_constructor); } @@ -1819,7 +1817,7 @@ TF_BUILTIN(PromisePrototypeFinally, PromiseBuiltinsAssembler) { Node* then_finally = nullptr; Node* catch_finally = nullptr; std::tie(then_finally, catch_finally) = - CreatePromiseFinallyFunctions(on_finally, constructor, native_context); + CreatePromiseFinallyFunctions(on_finally, constructor, native_context); var_then_finally.Bind(then_finally); var_catch_finally.Bind(catch_finally); Goto(&perform_finally); @@ -1850,7 +1848,7 @@ TF_BUILTIN(FulfillPromise, PromiseBuiltinsAssembler) { CSA_ASSERT(this, IsJSPromise(promise)); // 2. Let reactions be promise.[[PromiseFulfillReactions]]. - Node* const reactions = + TNode<Object> const reactions = LoadObjectField(promise, JSPromise::kReactionsOrResultOffset); // 3. Set promise.[[PromiseResult]] to value. @@ -1892,7 +1890,7 @@ TF_BUILTIN(RejectPromise, PromiseBuiltinsAssembler) { GotoIfNot(PromiseHasHandler(promise), &if_runtime); // 2. Let reactions be promise.[[PromiseRejectReactions]]. - Node* reactions = + TNode<Object> reactions = LoadObjectField(promise, JSPromise::kReactionsOrResultOffset); // 3. Set promise.[[PromiseResult]] to reason. @@ -1914,17 +1912,14 @@ TF_BUILTIN(RejectPromise, PromiseBuiltinsAssembler) { // ES #sec-promise-resolve-functions TF_BUILTIN(ResolvePromise, PromiseBuiltinsAssembler) { - Node* const promise = Parameter(Descriptor::kPromise); - Node* const resolution = Parameter(Descriptor::kResolution); - Node* const context = Parameter(Descriptor::kContext); - - CSA_ASSERT(this, TaggedIsNotSmi(promise)); - CSA_ASSERT(this, IsJSPromise(promise)); + TNode<JSPromise> const promise = CAST(Parameter(Descriptor::kPromise)); + TNode<Object> const resolution = CAST(Parameter(Descriptor::kResolution)); + TNode<Context> const context = CAST(Parameter(Descriptor::kContext)); Label do_enqueue(this), if_fulfill(this), if_reject(this, Label::kDeferred), if_runtime(this, Label::kDeferred); - VARIABLE(var_reason, MachineRepresentation::kTagged); - VARIABLE(var_then, MachineRepresentation::kTagged); + TVARIABLE(Object, var_reason); + TVARIABLE(Object, var_then); // If promise hook is enabled or the debugger is active, let // the runtime handle this operation, which greatly reduces @@ -1936,11 +1931,11 @@ TF_BUILTIN(ResolvePromise, PromiseBuiltinsAssembler) { // 6. If SameValue(resolution, promise) is true, then // We can use pointer comparison here, since the {promise} is guaranteed // to be a JSPromise inside this function and thus is reference comparable. - GotoIf(WordEqual(promise, resolution), &if_runtime); + GotoIf(TaggedEqual(promise, resolution), &if_runtime); // 7. If Type(resolution) is not Object, then GotoIf(TaggedIsSmi(resolution), &if_fulfill); - Node* const resolution_map = LoadMap(resolution); + TNode<Map> resolution_map = LoadMap(CAST(resolution)); GotoIfNot(IsJSReceiverMap(resolution_map), &if_fulfill); // We can skip the "then" lookup on {resolution} if its [[Prototype]] @@ -1948,21 +1943,19 @@ TF_BUILTIN(ResolvePromise, PromiseBuiltinsAssembler) { // is intact, as that guards the lookup path for the "then" property // on JSPromise instances which have the (initial) %PromisePrototype%. Label if_fast(this), if_receiver(this), if_slow(this, Label::kDeferred); - Node* const native_context = LoadNativeContext(context); + TNode<NativeContext> const native_context = LoadNativeContext(context); GotoIfForceSlowPath(&if_slow); GotoIf(IsPromiseThenProtectorCellInvalid(), &if_slow); GotoIfNot(IsJSPromiseMap(resolution_map), &if_receiver); - Node* const promise_prototype = + TNode<Object> const promise_prototype = LoadContextElement(native_context, Context::PROMISE_PROTOTYPE_INDEX); - Branch(WordEqual(LoadMapPrototype(resolution_map), promise_prototype), + Branch(TaggedEqual(LoadMapPrototype(resolution_map), promise_prototype), &if_fast, &if_slow); BIND(&if_fast); { // The {resolution} is a native Promise in this case. - Node* const then = - LoadContextElement(native_context, Context::PROMISE_THEN_INDEX); - var_then.Bind(then); + var_then = LoadContextElement(native_context, Context::PROMISE_THEN_INDEX); Goto(&do_enqueue); } @@ -1975,16 +1968,16 @@ TF_BUILTIN(ResolvePromise, PromiseBuiltinsAssembler) { // results from async generators. CSA_ASSERT(this, IsJSReceiverMap(resolution_map)); CSA_ASSERT(this, Word32BinaryNot(IsPromiseThenProtectorCellInvalid())); - Node* const iterator_result_map = + TNode<Object> const iterator_result_map = LoadContextElement(native_context, Context::ITERATOR_RESULT_MAP_INDEX); - Branch(WordEqual(resolution_map, iterator_result_map), &if_fulfill, + Branch(TaggedEqual(resolution_map, iterator_result_map), &if_fulfill, &if_slow); } BIND(&if_slow); { // 8. Let then be Get(resolution, "then"). - Node* const then = + TNode<Object> then = GetProperty(context, resolution, isolate()->factory()->then_string()); // 9. If then is an abrupt completion, then @@ -1992,9 +1985,9 @@ TF_BUILTIN(ResolvePromise, PromiseBuiltinsAssembler) { // 11. If IsCallable(thenAction) is false, then GotoIf(TaggedIsSmi(then), &if_fulfill); - Node* const then_map = LoadMap(then); + TNode<Map> const then_map = LoadMap(CAST(then)); GotoIfNot(IsCallableMap(then_map), &if_fulfill); - var_then.Bind(then); + var_then = then; Goto(&do_enqueue); } @@ -2032,7 +2025,7 @@ Node* PromiseBuiltinsAssembler::PerformPromiseAll( Label* if_exception, Variable* var_exception) { IteratorBuiltinsAssembler iter_assembler(state()); - TNode<NativeContext> native_context = Cast(LoadNativeContext(context)); + TNode<NativeContext> native_context = LoadNativeContext(context); // For catch prediction, don't treat the .then calls as handling it; // instead, recurse outwards. @@ -2120,9 +2113,9 @@ Node* PromiseBuiltinsAssembler::PerformPromiseAll( // Set resolveElement.[[Values]] to values. // Set resolveElement.[[Capability]] to resultCapability. // Set resolveElement.[[RemainingElements]] to remainingElementsCount. - Node* const resolve_element_fun = create_resolve_element_function( + TNode<Object> 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( + TNode<Object> 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 @@ -2148,7 +2141,7 @@ Node* PromiseBuiltinsAssembler::PerformPromiseAll( &if_slow); GotoIf(IsPromiseSpeciesProtectorCellInvalid(), &if_slow); GotoIf(TaggedIsSmi(next_value), &if_slow); - Node* const next_value_map = LoadMap(CAST(next_value)); + TNode<Map> const next_value_map = LoadMap(CAST(next_value)); BranchIfPromiseThenLookupChainIntact(native_context, next_value_map, &if_fast, &if_slow); @@ -2172,7 +2165,7 @@ Node* PromiseBuiltinsAssembler::PerformPromiseAll( // Perform ? Invoke(nextPromise, "then", « resolveElement, // resultCapability.[[Reject]] »). - Node* const then = + TNode<Object> const then = GetProperty(native_context, next_promise, factory()->then_string()); GotoIfException(then, &close_iterator, var_exception); @@ -2205,7 +2198,7 @@ Node* PromiseBuiltinsAssembler::PerformPromiseAll( // function and pass the larger indices via a separate context, but it // doesn't seem likely that we need this, and it's unclear how the rest // of the system deals with 2**21 live Promises anyways. - Node* const result = + TNode<Object> const result = CallRuntime(Runtime::kThrowRangeError, native_context, SmiConstant(MessageTemplate::kTooManyElementsInPromiseAll)); GotoIfException(result, &close_iterator, var_exception); @@ -2241,14 +2234,14 @@ Node* PromiseBuiltinsAssembler::PerformPromiseAll( // capacity here. We may already have elements here in case of some // fancy Thenable that calls the resolve callback immediately, so we need // to handle that correctly here. - Node* const values_array = LoadContextElement( + TNode<JSArray> const values_array = CAST(LoadContextElement( resolve_element_context, - PromiseBuiltins::kPromiseAllResolveElementValuesArraySlot); - Node* const old_elements = LoadElements(values_array); + PromiseBuiltins::kPromiseAllResolveElementValuesArraySlot)); + TNode<FixedArrayBase> const old_elements = LoadElements(values_array); TNode<Smi> const old_capacity = LoadFixedArrayBaseLength(old_elements); TNode<Smi> const new_capacity = var_index.value(); GotoIf(SmiGreaterThanOrEqual(old_capacity, new_capacity), &return_promise); - Node* const new_elements = + TNode<FixedArrayBase> const new_elements = AllocateFixedArray(PACKED_ELEMENTS, new_capacity, SMI_PARAMETERS, AllocationFlag::kAllowLargeObjectAllocation); CopyFixedArrayElements(PACKED_ELEMENTS, old_elements, PACKED_ELEMENTS, @@ -2263,9 +2256,9 @@ Node* PromiseBuiltinsAssembler::PerformPromiseAll( // « valuesArray »). BIND(&resolve_promise); { - Node* const resolve = + TNode<Object> const resolve = LoadObjectField(capability, PromiseCapability::kResolveOffset); - Node* const values_array = LoadContextElement( + TNode<Object> const values_array = LoadContextElement( resolve_element_context, PromiseBuiltins::kPromiseAllResolveElementValuesArraySlot); Node* const resolve_call = CallJS( @@ -2279,7 +2272,7 @@ Node* PromiseBuiltinsAssembler::PerformPromiseAll( BIND(&return_promise); } - Node* const promise = + TNode<Object> const promise = LoadObjectField(capability, PromiseCapability::kPromiseOffset); return promise; } @@ -2298,9 +2291,9 @@ void PromiseBuiltinsAssembler::Generate_PromiseAll( // Let promiseCapability be ? NewPromiseCapability(C). // Don't fire debugEvent so that forwarding the rejection through all does not // trigger redundant ExceptionEvents - Node* const debug_event = FalseConstant(); - Node* const capability = CallBuiltin(Builtins::kNewPromiseCapability, context, - receiver, debug_event); + TNode<Oddball> const debug_event = FalseConstant(); + TNode<PromiseCapability> const capability = CAST(CallBuiltin( + Builtins::kNewPromiseCapability, context, receiver, debug_event)); VARIABLE(var_exception, MachineRepresentation::kTagged, TheHoleConstant()); Label reject_promise(this, &var_exception, Label::kDeferred); @@ -2325,12 +2318,12 @@ void PromiseBuiltinsAssembler::Generate_PromiseAll( { // Exception must be bound to a JS value. CSA_SLOW_ASSERT(this, IsNotTheHole(var_exception.value())); - Node* const reject = + TNode<Object> const reject = LoadObjectField(capability, PromiseCapability::kRejectOffset); CallJS(CodeFactory::Call(isolate(), ConvertReceiverMode::kNullOrUndefined), context, reject, UndefinedConstant(), var_exception.value()); - Node* const promise = + TNode<Object> const promise = LoadObjectField(capability, PromiseCapability::kPromiseOffset); Return(promise); } @@ -2397,7 +2390,7 @@ void PromiseBuiltinsAssembler::Generate_PromiseAllResolveElementClosure( this, SmiEqual(LoadObjectField<Smi>(context, Context::kLengthOffset), SmiConstant(PromiseBuiltins::kPromiseAllResolveElementLength))); - TNode<NativeContext> native_context = Cast(LoadNativeContext(context)); + TNode<NativeContext> native_context = LoadNativeContext(context); StoreObjectField(function, JSFunction::kContextOffset, native_context); // Update the value depending on whether Promise.all or @@ -2578,19 +2571,19 @@ TF_BUILTIN(PromiseRace, PromiseBuiltinsAssembler) { Node* const receiver = Parameter(Descriptor::kReceiver); TNode<Context> const context = CAST(Parameter(Descriptor::kContext)); - ThrowIfNotJSReceiver(context, receiver, MessageTemplate::kCalledOnNonObject, - "Promise.race"); + ThrowIfNotJSReceiver(context, CAST(receiver), + MessageTemplate::kCalledOnNonObject, "Promise.race"); // Let promiseCapability be ? NewPromiseCapability(C). // Don't fire debugEvent so that forwarding the rejection through all does not // trigger redundant ExceptionEvents - Node* const debug_event = FalseConstant(); - Node* const capability = CallBuiltin(Builtins::kNewPromiseCapability, context, - receiver, debug_event); + TNode<Oddball> const debug_event = FalseConstant(); + TNode<PromiseCapability> const capability = CAST(CallBuiltin( + Builtins::kNewPromiseCapability, context, receiver, debug_event)); - Node* const resolve = + TNode<Object> const resolve = LoadObjectField(capability, PromiseCapability::kResolveOffset); - Node* const reject = + TNode<Object> const reject = LoadObjectField(capability, PromiseCapability::kRejectOffset); Label close_iterator(this, Label::kDeferred); @@ -2613,7 +2606,7 @@ TF_BUILTIN(PromiseRace, PromiseBuiltinsAssembler) { // as that guards the lookup path for the "resolve" property on the // Promise constructor. Label loop(this), break_loop(this), if_slow(this, Label::kDeferred); - Node* const native_context = LoadNativeContext(context); + TNode<NativeContext> const native_context = LoadNativeContext(context); TVARIABLE(Object, var_promise_resolve_function, UndefinedConstant()); GotoIfNotPromiseResolveLookupChainIntact(native_context, receiver, &if_slow); @@ -2662,7 +2655,7 @@ TF_BUILTIN(PromiseRace, PromiseBuiltinsAssembler) { // Perform ? Invoke(nextPromise, "then", « resolveElement, // resultCapability.[[Reject]] »). - Node* const then = + TNode<Object> const then = GetProperty(context, next_promise, factory()->then_string()); GotoIfException(then, &close_iterator, &var_exception); @@ -2694,12 +2687,12 @@ TF_BUILTIN(PromiseRace, PromiseBuiltinsAssembler) { BIND(&reject_promise); { - Node* const reject = + TNode<Object> const reject = LoadObjectField(capability, PromiseCapability::kRejectOffset); CallJS(CodeFactory::Call(isolate(), ConvertReceiverMode::kNullOrUndefined), context, reject, UndefinedConstant(), var_exception.value()); - Node* const promise = + TNode<Object> const promise = LoadObjectField(capability, PromiseCapability::kPromiseOffset); Return(promise); } diff --git a/deps/v8/src/builtins/builtins-promise-gen.h b/deps/v8/src/builtins/builtins-promise-gen.h index 71443ca920..633e3321aa 100644 --- a/deps/v8/src/builtins/builtins-promise-gen.h +++ b/deps/v8/src/builtins/builtins-promise-gen.h @@ -35,9 +35,6 @@ class V8_EXPORT_PRIVATE PromiseBuiltinsAssembler : public CodeStubAssembler { Node* AllocatePromiseReaction(Node* next, Node* promise_or_capability, Node* fulfill_handler, Node* reject_handler); - Node* AllocatePromiseReactionJobTask(RootIndex map_root_index, Node* context, - Node* argument, Node* handler, - Node* promise_or_capability); Node* AllocatePromiseReactionJobTask(Node* map, Node* context, Node* argument, Node* handler, Node* promise_or_capability); @@ -91,10 +88,10 @@ class V8_EXPORT_PRIVATE PromiseBuiltinsAssembler : public CodeStubAssembler { // that guards the lookup path for the "resolve" property on the %Promise% // intrinsic object. void BranchIfPromiseResolveLookupChainIntact(Node* native_context, - Node* constructor, + SloppyTNode<Object> constructor, Label* if_fast, Label* if_slow); void GotoIfNotPromiseResolveLookupChainIntact(Node* native_context, - Node* constructor, + SloppyTNode<Object> constructor, Label* if_slow); // We can shortcut the SpeciesConstructor on {promise_map} if it's @@ -120,7 +117,8 @@ class V8_EXPORT_PRIVATE PromiseBuiltinsAssembler : public CodeStubAssembler { template <typename... TArgs> Node* InvokeThen(Node* native_context, Node* receiver, TArgs... args); - void BranchIfAccessCheckFailed(Node* context, Node* native_context, + void BranchIfAccessCheckFailed(SloppyTNode<Context> context, + SloppyTNode<Context> native_context, Node* promise_constructor, Node* executor, Label* if_noaccess); @@ -153,13 +151,14 @@ class V8_EXPORT_PRIVATE PromiseBuiltinsAssembler : public CodeStubAssembler { void SetPromiseHandledByIfTrue(Node* context, Node* condition, Node* promise, const NodeGenerator& handled_by); - Node* PromiseStatus(Node* promise); + TNode<Word32T> PromiseStatus(Node* promise); void PromiseReactionJob(Node* context, Node* argument, Node* handler, Node* promise_or_capability, PromiseReaction::Type type); - Node* IsPromiseStatus(Node* actual, v8::Promise::PromiseState expected); + TNode<BoolT> IsPromiseStatus(TNode<Word32T> actual, + v8::Promise::PromiseState expected); void PromiseSetStatus(Node* promise, v8::Promise::PromiseState status); Node* AllocateJSPromise(Node* context); diff --git a/deps/v8/src/builtins/builtins-proxy-gen.cc b/deps/v8/src/builtins/builtins-proxy-gen.cc index 948540ea5f..bb1137735c 100644 --- a/deps/v8/src/builtins/builtins-proxy-gen.cc +++ b/deps/v8/src/builtins/builtins-proxy-gen.cc @@ -8,6 +8,7 @@ #include "src/builtins/builtins.h" #include "src/logging/counters.h" +#include "src/objects/js-proxy.h" #include "src/objects/objects-inl.h" namespace v8 { @@ -21,7 +22,7 @@ compiler::TNode<JSProxy> ProxiesCodeStubAssembler::AllocateProxy( Label callable_target(this), constructor_target(this), none_target(this), create_proxy(this); - Node* nativeContext = LoadNativeContext(context); + TNode<NativeContext> nativeContext = LoadNativeContext(context); Branch(IsCallable(target), &callable_target, &none_target); @@ -47,7 +48,7 @@ compiler::TNode<JSProxy> ProxiesCodeStubAssembler::AllocateProxy( } BIND(&create_proxy); - Node* proxy = Allocate(JSProxy::kSize); + TNode<HeapObject> proxy = Allocate(JSProxy::kSize); StoreMapNoWriteBarrier(proxy, map.value()); StoreObjectFieldRoot(proxy, JSProxy::kPropertiesOrHashOffset, RootIndex::kEmptyPropertyDictionary); @@ -69,8 +70,8 @@ Node* ProxiesCodeStubAssembler::AllocateJSArrayForCodeStubArguments( GotoIf(SmiEqual(length, SmiConstant(0)), &if_empty_array); { Label if_large_object(this, Label::kDeferred); - Node* allocated_elements = AllocateFixedArray(PACKED_ELEMENTS, argc, mode, - kAllowLargeObjectAllocation); + TNode<FixedArrayBase> allocated_elements = AllocateFixedArray( + PACKED_ELEMENTS, argc, mode, kAllowLargeObjectAllocation); elements.Bind(allocated_elements); TVARIABLE(IntPtrT, offset, @@ -104,7 +105,7 @@ Node* ProxiesCodeStubAssembler::AllocateJSArrayForCodeStubArguments( BIND(&allocate_js_array); // Allocate the result JSArray. - Node* native_context = LoadNativeContext(context); + TNode<NativeContext> native_context = LoadNativeContext(context); TNode<Map> array_map = LoadJSArrayElementsMap(PACKED_ELEMENTS, native_context); TNode<JSArray> array = @@ -115,23 +116,24 @@ Node* ProxiesCodeStubAssembler::AllocateJSArrayForCodeStubArguments( Node* ProxiesCodeStubAssembler::CreateProxyRevokeFunctionContext( Node* proxy, Node* native_context) { - Node* const context = Allocate(FixedArray::SizeFor(kProxyContextLength)); + TNode<HeapObject> const context = + Allocate(FixedArray::SizeFor(kProxyContextLength)); StoreMapNoWriteBarrier(context, RootIndex::kFunctionContextMap); InitializeFunctionContext(native_context, context, kProxyContextLength); - StoreContextElementNoWriteBarrier(context, kProxySlot, proxy); + StoreContextElementNoWriteBarrier(CAST(context), kProxySlot, proxy); return context; } compiler::TNode<JSFunction> ProxiesCodeStubAssembler::AllocateProxyRevokeFunction(TNode<Context> context, TNode<JSProxy> proxy) { - Node* const native_context = LoadNativeContext(context); + TNode<NativeContext> const native_context = LoadNativeContext(context); Node* const proxy_context = CreateProxyRevokeFunctionContext(proxy, native_context); - Node* const revoke_map = LoadContextElement( + TNode<Object> const revoke_map = LoadContextElement( native_context, Context::STRICT_FUNCTION_WITHOUT_PROTOTYPE_MAP_INDEX); - Node* const revoke_info = + TNode<Object> const revoke_info = LoadContextElement(native_context, Context::PROXY_REVOKE_SHARED_FUN); return CAST(AllocateFunctionWithMapAndContext(revoke_map, revoke_info, @@ -140,11 +142,10 @@ ProxiesCodeStubAssembler::AllocateProxyRevokeFunction(TNode<Context> context, TF_BUILTIN(CallProxy, ProxiesCodeStubAssembler) { Node* argc = Parameter(Descriptor::kActualArgumentsCount); - Node* argc_ptr = ChangeInt32ToIntPtr(argc); - Node* proxy = Parameter(Descriptor::kFunction); + TNode<IntPtrT> argc_ptr = ChangeInt32ToIntPtr(argc); + TNode<JSProxy> proxy = CAST(Parameter(Descriptor::kFunction)); Node* context = Parameter(Descriptor::kContext); - CSA_ASSERT(this, IsJSProxy(proxy)); CSA_ASSERT(this, IsCallable(proxy)); PerformStackCheck(CAST(context)); @@ -153,7 +154,8 @@ TF_BUILTIN(CallProxy, ProxiesCodeStubAssembler) { trap_undefined(this); // 1. Let handler be the value of the [[ProxyHandler]] internal slot of O. - Node* handler = LoadObjectField(proxy, JSProxy::kHandlerOffset); + TNode<HeapObject> handler = + CAST(LoadObjectField(proxy, JSProxy::kHandlerOffset)); // 2. If handler is null, throw a TypeError exception. CSA_ASSERT(this, IsNullOrJSReceiver(handler)); @@ -163,7 +165,7 @@ TF_BUILTIN(CallProxy, ProxiesCodeStubAssembler) { CSA_ASSERT(this, IsJSReceiver(handler)); // 4. Let target be the value of the [[ProxyTarget]] internal slot of O. - Node* target = LoadObjectField(proxy, JSProxy::kTargetOffset); + TNode<Object> target = LoadObjectField(proxy, JSProxy::kTargetOffset); // 5. Let trap be ? GetMethod(handler, "apply"). // 6. If trap is undefined, then @@ -171,7 +173,7 @@ TF_BUILTIN(CallProxy, ProxiesCodeStubAssembler) { Node* trap = GetMethod(context, handler, trap_name, &trap_undefined); CodeStubArguments args(this, argc_ptr); - Node* receiver = args.GetReceiver(); + TNode<Object> receiver = args.GetReceiver(); // 7. Let argArray be CreateArrayFromList(argumentsList). Node* array = AllocateJSArrayForCodeStubArguments(context, args, argc_ptr, @@ -194,7 +196,7 @@ TF_BUILTIN(CallProxy, ProxiesCodeStubAssembler) { TF_BUILTIN(ConstructProxy, ProxiesCodeStubAssembler) { Node* argc = Parameter(Descriptor::kActualArgumentsCount); - Node* argc_ptr = ChangeInt32ToIntPtr(argc); + TNode<IntPtrT> argc_ptr = ChangeInt32ToIntPtr(argc); Node* proxy = Parameter(Descriptor::kTarget); Node* new_target = Parameter(Descriptor::kNewTarget); Node* context = Parameter(Descriptor::kContext); @@ -206,7 +208,8 @@ TF_BUILTIN(ConstructProxy, ProxiesCodeStubAssembler) { trap_undefined(this), not_an_object(this, Label::kDeferred); // 1. Let handler be the value of the [[ProxyHandler]] internal slot of O. - Node* handler = LoadObjectField(proxy, JSProxy::kHandlerOffset); + TNode<HeapObject> handler = + CAST(LoadObjectField(proxy, JSProxy::kHandlerOffset)); // 2. If handler is null, throw a TypeError exception. CSA_ASSERT(this, IsNullOrJSReceiver(handler)); @@ -216,7 +219,7 @@ TF_BUILTIN(ConstructProxy, ProxiesCodeStubAssembler) { CSA_ASSERT(this, IsJSReceiver(handler)); // 4. Let target be the value of the [[ProxyTarget]] internal slot of O. - Node* target = LoadObjectField(proxy, JSProxy::kTargetOffset); + TNode<Object> target = LoadObjectField(proxy, JSProxy::kTargetOffset); // 5. Let trap be ? GetMethod(handler, "construct"). // 6. If trap is undefined, then @@ -248,7 +251,7 @@ TF_BUILTIN(ConstructProxy, ProxiesCodeStubAssembler) { BIND(&trap_undefined); { // 6.a. Assert: target has a [[Construct]] internal method. - CSA_ASSERT(this, IsConstructor(target)); + CSA_ASSERT(this, IsConstructor(CAST(target))); // 6.b. Return ? Construct(target, argumentsList, newTarget). TailCallStub(CodeFactory::Construct(isolate()), context, target, new_target, @@ -264,7 +267,7 @@ void ProxiesCodeStubAssembler::CheckGetSetTrapResult( TNode<Name> name, TNode<Object> trap_result, JSProxy::AccessKind access_kind) { // TODO(mslekova): Think of a better name for the trap_result param. - Node* map = LoadMap(target); + TNode<Map> map = LoadMap(target); VARIABLE(var_value, MachineRepresentation::kTagged); VARIABLE(var_details, MachineRepresentation::kWord32); VARIABLE(var_raw_value, MachineRepresentation::kTagged); @@ -273,7 +276,7 @@ void ProxiesCodeStubAssembler::CheckGetSetTrapResult( check_passed(this); GotoIfNot(IsUniqueNameNoIndex(name), &check_in_runtime); - Node* instance_type = LoadInstanceType(target); + TNode<Uint16T> instance_type = LoadInstanceType(target); TryGetOwnProperty(context, target, target, map, instance_type, name, &if_found_value, &var_value, &var_details, &var_raw_value, &check_passed, &check_in_runtime, kReturnAccessorPair); @@ -296,8 +299,8 @@ void ProxiesCodeStubAssembler::CheckGetSetTrapResult( BIND(&check_data); { - Node* read_only = IsSetWord32(var_details.value(), - PropertyDetails::kAttributesReadOnlyMask); + TNode<BoolT> read_only = IsSetWord32( + var_details.value(), PropertyDetails::kAttributesReadOnlyMask); GotoIfNot(read_only, &check_passed); // If SameValue(trapResult, targetDesc.[[Value]]) is false, @@ -314,7 +317,7 @@ void ProxiesCodeStubAssembler::CheckGetSetTrapResult( Label continue_check(this, Label::kDeferred); // 10.b. If IsAccessorDescriptor(targetDesc) is true and // targetDesc.[[Get]] is undefined, then: - Node* getter = + TNode<Object> getter = LoadObjectField(accessor_pair, AccessorPair::kGetterOffset); // Here we check for null as well because if the getter was never // defined it's set as null. @@ -328,7 +331,7 @@ void ProxiesCodeStubAssembler::CheckGetSetTrapResult( } else { // 11.b.i. If targetDesc.[[Set]] is undefined, throw a TypeError // exception. - Node* setter = + TNode<Object> setter = LoadObjectField(accessor_pair, AccessorPair::kSetterOffset); GotoIf(IsUndefined(setter), &throw_non_configurable_accessor); GotoIf(IsNull(setter), &throw_non_configurable_accessor); @@ -372,7 +375,7 @@ void ProxiesCodeStubAssembler::CheckHasTrapResult(TNode<Context> context, TNode<JSReceiver> target, TNode<JSProxy> proxy, TNode<Name> name) { - Node* target_map = LoadMap(target); + TNode<Map> target_map = LoadMap(target); VARIABLE(var_value, MachineRepresentation::kTagged); VARIABLE(var_details, MachineRepresentation::kWord32); VARIABLE(var_raw_value, MachineRepresentation::kTagged); @@ -384,7 +387,7 @@ void ProxiesCodeStubAssembler::CheckHasTrapResult(TNode<Context> context, // 9.a. Let targetDesc be ? target.[[GetOwnProperty]](P). GotoIfNot(IsUniqueNameNoIndex(name), &check_in_runtime); - Node* instance_type = LoadInstanceType(target); + TNode<Uint16T> instance_type = LoadInstanceType(target); TryGetOwnProperty(context, target, target, target_map, instance_type, name, &if_found_value, &var_value, &var_details, &var_raw_value, &check_passed, &check_in_runtime, kReturnAccessorPair); @@ -394,12 +397,12 @@ void ProxiesCodeStubAssembler::CheckHasTrapResult(TNode<Context> context, { // 9.b.i. If targetDesc.[[Configurable]] is false, throw a TypeError // exception. - Node* non_configurable = IsSetWord32( + TNode<BoolT> non_configurable = IsSetWord32( var_details.value(), PropertyDetails::kAttributesDontDeleteMask); GotoIf(non_configurable, &throw_non_configurable); // 9.b.ii. Let extensibleTarget be ? IsExtensible(target). - Node* target_extensible = IsExtensibleMap(target_map); + TNode<BoolT> target_extensible = IsExtensibleMap(target_map); // 9.b.iii. If extensibleTarget is false, throw a TypeError exception. GotoIfNot(target_extensible, &throw_non_extensible); @@ -437,7 +440,7 @@ void ProxiesCodeStubAssembler::CheckDeleteTrapResult(TNode<Context> context, // 10. Let targetDesc be ? target.[[GetOwnProperty]](P). GotoIfNot(IsUniqueNameNoIndex(name), &check_in_runtime); - TNode<Int32T> instance_type = LoadInstanceType(target); + TNode<Uint16T> instance_type = LoadInstanceType(target); TryGetOwnProperty(context, target, target, target_map, instance_type, name, &if_found_value, &var_value, &var_details, &var_raw_value, &check_passed, &check_in_runtime, kReturnAccessorPair); diff --git a/deps/v8/src/builtins/builtins-reflect-gen.cc b/deps/v8/src/builtins/builtins-reflect-gen.cc index dade25b7c7..744a443ecc 100644 --- a/deps/v8/src/builtins/builtins-reflect-gen.cc +++ b/deps/v8/src/builtins/builtins-reflect-gen.cc @@ -13,10 +13,10 @@ namespace internal { TF_BUILTIN(ReflectHas, CodeStubAssembler) { Node* target = Parameter(Descriptor::kTarget); Node* key = Parameter(Descriptor::kKey); - Node* context = Parameter(Descriptor::kContext); + TNode<Context> context = CAST(Parameter(Descriptor::kContext)); - ThrowIfNotJSReceiver(context, target, MessageTemplate::kCalledOnNonObject, - "Reflect.has"); + ThrowIfNotJSReceiver(context, CAST(target), + MessageTemplate::kCalledOnNonObject, "Reflect.has"); Return(CallBuiltin(Builtins::kHasProperty, context, target, key)); } diff --git a/deps/v8/src/builtins/builtins-regexp-gen.cc b/deps/v8/src/builtins/builtins-regexp-gen.cc index d53518ff7e..f879d70c67 100644 --- a/deps/v8/src/builtins/builtins-regexp-gen.cc +++ b/deps/v8/src/builtins/builtins-regexp-gen.cc @@ -10,6 +10,8 @@ #include "src/builtins/growable-fixed-array-gen.h" #include "src/codegen/code-factory.h" #include "src/codegen/code-stub-assembler.h" +#include "src/codegen/macro-assembler.h" +#include "src/execution/protectors.h" #include "src/heap/factory-inl.h" #include "src/logging/counters.h" #include "src/objects/js-regexp-string-iterator.h" @@ -24,12 +26,55 @@ using compiler::Node; template <class T> using TNode = compiler::TNode<T>; +// Tail calls the regular expression interpreter. +// static +void Builtins::Generate_RegExpInterpreterTrampoline(MacroAssembler* masm) { + ExternalReference interpreter_code_entry = + ExternalReference::re_match_for_call_from_js(masm->isolate()); + masm->Jump(interpreter_code_entry); +} + TNode<Smi> RegExpBuiltinsAssembler::SmiZero() { return SmiConstant(0); } TNode<IntPtrT> RegExpBuiltinsAssembler::IntPtrZero() { return IntPtrConstant(0); } +// If code is a builtin, return the address to the (possibly embedded) builtin +// code entry, otherwise return the entry of the code object itself. +TNode<RawPtrT> RegExpBuiltinsAssembler::LoadCodeObjectEntry(TNode<Code> code) { + TVARIABLE(RawPtrT, var_result); + + Label if_code_is_off_heap(this), out(this); + TNode<Int32T> builtin_index = UncheckedCast<Int32T>( + LoadObjectField(code, Code::kBuiltinIndexOffset, MachineType::Int32())); + { + GotoIfNot(Word32Equal(builtin_index, Int32Constant(Builtins::kNoBuiltinId)), + &if_code_is_off_heap); + var_result = ReinterpretCast<RawPtrT>( + IntPtrAdd(BitcastTaggedToWord(code), + IntPtrConstant(Code::kHeaderSize - kHeapObjectTag))); + Goto(&out); + } + + BIND(&if_code_is_off_heap); + { + TNode<IntPtrT> builtin_entry_offset_from_isolate_root = + IntPtrAdd(IntPtrConstant(IsolateData::builtin_entry_table_offset()), + ChangeInt32ToIntPtr(Word32Shl( + builtin_index, Int32Constant(kSystemPointerSizeLog2)))); + + var_result = ReinterpretCast<RawPtrT>( + Load(MachineType::Pointer(), + ExternalConstant(ExternalReference::isolate_root(isolate())), + builtin_entry_offset_from_isolate_root)); + Goto(&out); + } + + BIND(&out); + return var_result.value(); +} + // ----------------------------------------------------------------------------- // ES6 section 21.2 RegExp Objects @@ -131,8 +176,8 @@ void RegExpBuiltinsAssembler::FastStoreLastIndex(TNode<JSRegExp> regexp, void RegExpBuiltinsAssembler::SlowStoreLastIndex(SloppyTNode<Context> context, SloppyTNode<Object> regexp, - SloppyTNode<Number> value) { - TNode<Name> name = HeapConstant(isolate()->factory()->lastIndex_string()); + SloppyTNode<Object> value) { + TNode<String> name = HeapConstant(isolate()->factory()->lastIndex_string()); SetPropertyStrict(context, regexp, name, value); } @@ -236,7 +281,7 @@ TNode<JSRegExpResult> RegExpBuiltinsAssembler::ConstructNewResultFromMatchInfo( // index at odd indices. TNode<Object> maybe_names = LoadFixedArrayElement(data, JSRegExp::kIrregexpCaptureNameMapIndex); - GotoIf(WordEqual(maybe_names, SmiZero()), &out); + GotoIf(TaggedEqual(maybe_names, SmiZero()), &out); // One or more named captures exist, add a property for each one. @@ -249,7 +294,7 @@ TNode<JSRegExpResult> RegExpBuiltinsAssembler::ConstructNewResultFromMatchInfo( // root list. TNode<IntPtrT> num_properties = WordSar(names_length, 1); - TNode<Context> native_context = LoadNativeContext(context); + TNode<NativeContext> native_context = LoadNativeContext(context); TNode<Map> map = CAST(LoadContextElement( native_context, Context::SLOW_OBJECT_WITH_NULL_PROTOTYPE_MAP)); TNode<NameDictionary> properties = @@ -320,11 +365,11 @@ void RegExpBuiltinsAssembler::GetStringPointers( ? UINT8_ELEMENTS : UINT16_ELEMENTS; - Node* const from_offset = ElementOffsetFromIndex( + TNode<IntPtrT> const from_offset = ElementOffsetFromIndex( IntPtrAdd(offset, last_index), kind, INTPTR_PARAMETERS); var_string_start->Bind(IntPtrAdd(string_data, from_offset)); - Node* const to_offset = ElementOffsetFromIndex( + TNode<IntPtrT> const to_offset = ElementOffsetFromIndex( IntPtrAdd(offset, string_length), kind, INTPTR_PARAMETERS); var_string_end->Bind(IntPtrAdd(string_data, to_offset)); } @@ -340,9 +385,8 @@ TNode<HeapObject> RegExpBuiltinsAssembler::RegExpExecInternal( // External constants. TNode<ExternalReference> isolate_address = ExternalConstant(ExternalReference::isolate_address(isolate())); - TNode<ExternalReference> regexp_stack_memory_address_address = - ExternalConstant( - ExternalReference::address_of_regexp_stack_memory_address(isolate())); + TNode<ExternalReference> regexp_stack_memory_top_address = ExternalConstant( + ExternalReference::address_of_regexp_stack_memory_top_address(isolate())); TNode<ExternalReference> regexp_stack_memory_size_address = ExternalConstant( ExternalReference::address_of_regexp_stack_memory_size(isolate())); TNode<ExternalReference> static_offsets_vector_address = ExternalConstant( @@ -374,7 +418,9 @@ TNode<HeapObject> RegExpBuiltinsAssembler::RegExpExecInternal( data, IntPtrConstant(JSRegExp::kTagIndex)); int32_t values[] = { - JSRegExp::IRREGEXP, JSRegExp::ATOM, JSRegExp::NOT_COMPILED, + JSRegExp::IRREGEXP, + JSRegExp::ATOM, + JSRegExp::NOT_COMPILED, }; Label* labels[] = {&next, &atom, &runtime}; @@ -398,24 +444,17 @@ TNode<HeapObject> RegExpBuiltinsAssembler::RegExpExecInternal( &runtime); } - // Ensure that a RegExp stack is allocated. This check is after branching off - // for ATOM regexps to avoid unnecessary trips to runtime. - { - TNode<IntPtrT> stack_size = UncheckedCast<IntPtrT>( - Load(MachineType::IntPtr(), regexp_stack_memory_size_address)); - GotoIf(IntPtrEqual(stack_size, IntPtrZero()), &runtime); - } - // Unpack the string if possible. to_direct.TryToDirect(&runtime); - // Load the irregexp code object and offsets into the subject string. Both - // depend on whether the string is one- or two-byte. + // Load the irregexp code or bytecode object and offsets into the subject + // string. Both depend on whether the string is one- or two-byte. TVARIABLE(RawPtrT, var_string_start); TVARIABLE(RawPtrT, var_string_end); TVARIABLE(Object, var_code); + TVARIABLE(Object, var_bytecode); { TNode<RawPtrT> direct_string_data = to_direct.PointerToData(&runtime); @@ -431,6 +470,8 @@ TNode<HeapObject> RegExpBuiltinsAssembler::RegExpExecInternal( &var_string_start, &var_string_end); var_code = UnsafeLoadFixedArrayElement(data, JSRegExp::kIrregexpLatin1CodeIndex); + var_bytecode = UnsafeLoadFixedArrayElement( + data, JSRegExp::kIrregexpLatin1BytecodeIndex); Goto(&next); } @@ -441,6 +482,8 @@ TNode<HeapObject> RegExpBuiltinsAssembler::RegExpExecInternal( &var_string_start, &var_string_end); var_code = UnsafeLoadFixedArrayElement(data, JSRegExp::kIrregexpUC16CodeIndex); + var_bytecode = UnsafeLoadFixedArrayElement( + data, JSRegExp::kIrregexpUC16BytecodeIndex); Goto(&next); } @@ -462,9 +505,32 @@ TNode<HeapObject> RegExpBuiltinsAssembler::RegExpExecInternal( #endif GotoIf(TaggedIsSmi(var_code.value()), &runtime); - GotoIfNot(IsCode(CAST(var_code.value())), &runtime); TNode<Code> code = CAST(var_code.value()); + // Tier-up in runtime if ticks are non-zero and tier-up hasn't happened yet + // and ensure that a RegExp stack is allocated when using compiled Irregexp. + { + Label next(this), check_tier_up(this); + GotoIfNot(TaggedIsSmi(var_bytecode.value()), &check_tier_up); + CSA_ASSERT(this, SmiEqual(CAST(var_bytecode.value()), + SmiConstant(JSRegExp::kUninitializedValue))); + + // Ensure RegExp stack is allocated. + TNode<IntPtrT> stack_size = UncheckedCast<IntPtrT>( + Load(MachineType::IntPtr(), regexp_stack_memory_size_address)); + GotoIf(IntPtrEqual(stack_size, IntPtrZero()), &runtime); + Goto(&next); + + // Check if tier-up is requested. + BIND(&check_tier_up); + TNode<Smi> ticks = CAST( + UnsafeLoadFixedArrayElement(data, JSRegExp::kIrregexpTierUpTicksIndex)); + GotoIf(SmiToInt32(ticks), &runtime); + + Goto(&next); + BIND(&next); + } + Label if_success(this), if_exception(this, Label::kDeferred); { IncrementCounter(isolate()->counters()->regexp_entry_native(), 1); @@ -486,11 +552,13 @@ TNode<HeapObject> RegExpBuiltinsAssembler::RegExpExecInternal( MachineType arg1_type = type_int32; TNode<Int32T> arg1 = TruncateIntPtrToInt32(int_last_index); - // Argument 2: Start of string data. + // Argument 2: Start of string data. This argument is ignored in the + // interpreter. MachineType arg2_type = type_ptr; TNode<RawPtrT> arg2 = var_string_start.value(); - // Argument 3: End of string data. + // Argument 3: End of string data. This argument is ignored in the + // interpreter. MachineType arg3_type = type_ptr; TNode<RawPtrT> arg3 = var_string_end.value(); @@ -498,41 +566,50 @@ TNode<HeapObject> RegExpBuiltinsAssembler::RegExpExecInternal( MachineType arg4_type = type_ptr; TNode<ExternalReference> arg4 = static_offsets_vector_address; - // Argument 5: Set the number of capture registers to zero to force global - // regexps to behave as non-global. This does not affect non-global - // regexps. + // Argument 5: Number of capture registers. + // Setting this to the number of registers required to store all captures + // forces global regexps to behave as non-global. + TNode<Smi> capture_count = CAST(UnsafeLoadFixedArrayElement( + data, JSRegExp::kIrregexpCaptureCountIndex)); + // capture_count is the number of captures without the match itself. + // Required registers = (capture_count + 1) * 2. + STATIC_ASSERT(Internals::IsValidSmi((JSRegExp::kMaxCaptures + 1) << 1)); + TNode<Smi> register_count = + SmiShl(SmiAdd(capture_count, SmiConstant(1)), 1); + MachineType arg5_type = type_int32; - TNode<Int32T> arg5 = Int32Constant(0); + TNode<Int32T> arg5 = SmiToInt32(register_count); - // Argument 6: Start (high end) of backtracking stack memory area. - TNode<RawPtrT> stack_start = UncheckedCast<RawPtrT>( - Load(MachineType::Pointer(), regexp_stack_memory_address_address)); - TNode<IntPtrT> stack_size = UncheckedCast<IntPtrT>( - Load(MachineType::IntPtr(), regexp_stack_memory_size_address)); - TNode<RawPtrT> stack_end = - ReinterpretCast<RawPtrT>(IntPtrAdd(stack_start, stack_size)); + // Argument 6: Start (high end) of backtracking stack memory area. This + // argument is ignored in the interpreter. + TNode<RawPtrT> stack_top = UncheckedCast<RawPtrT>( + Load(MachineType::Pointer(), regexp_stack_memory_top_address)); MachineType arg6_type = type_ptr; - TNode<RawPtrT> arg6 = stack_end; + TNode<RawPtrT> arg6 = stack_top; // Argument 7: Indicate that this is a direct call from JavaScript. MachineType arg7_type = type_int32; - TNode<Int32T> arg7 = Int32Constant(1); + TNode<Int32T> arg7 = Int32Constant(RegExp::CallOrigin::kFromJs); // Argument 8: Pass current isolate address. MachineType arg8_type = type_ptr; TNode<ExternalReference> arg8 = isolate_address; - TNode<RawPtrT> code_entry = ReinterpretCast<RawPtrT>( - IntPtrAdd(BitcastTaggedToWord(code), - IntPtrConstant(Code::kHeaderSize - kHeapObjectTag))); + // Argument 9: Regular expression object. This argument is ignored in native + // irregexp code. + MachineType arg9_type = type_tagged; + TNode<JSRegExp> arg9 = regexp; + + TNode<RawPtrT> code_entry = LoadCodeObjectEntry(code); 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))); + std::make_pair(arg7_type, arg7), std::make_pair(arg8_type, arg8), + std::make_pair(arg9_type, arg9))); // Check the result. // We expect exactly one result since we force the called regexp to behave @@ -734,7 +811,7 @@ RegExpBuiltinsAssembler::RegExpPrototypeExecBodyWithoutResult( BIND(&run_exec); { // Get last match info from the context. - TNode<Context> native_context = LoadNativeContext(context); + TNode<NativeContext> native_context = LoadNativeContext(context); TNode<RegExpMatchInfo> last_match_info = CAST(LoadContextElement( native_context, Context::REGEXP_LAST_MATCH_INFO_INDEX)); @@ -771,8 +848,8 @@ RegExpBuiltinsAssembler::RegExpPrototypeExecBodyWithoutResult( TNode<RegExpMatchInfo> RegExpBuiltinsAssembler::RegExpPrototypeExecBodyWithoutResultFast( - TNode<Context> context, TNode<JSReceiver> maybe_regexp, - TNode<String> string, Label* if_didnotmatch) { + TNode<Context> context, TNode<JSRegExp> maybe_regexp, TNode<String> string, + Label* if_didnotmatch) { return RegExpPrototypeExecBodyWithoutResult(context, maybe_regexp, string, if_didnotmatch, true); } @@ -805,36 +882,21 @@ TNode<HeapObject> RegExpBuiltinsAssembler::RegExpPrototypeExecBody( return var_result.value(); } -Node* RegExpBuiltinsAssembler::ThrowIfNotJSReceiver( - Node* context, Node* maybe_receiver, MessageTemplate msg_template, - char const* method_name) { - Label out(this), throw_exception(this, Label::kDeferred); - VARIABLE(var_value_map, MachineRepresentation::kTagged); - - GotoIf(TaggedIsSmi(maybe_receiver), &throw_exception); - - // Load the instance type of the {value}. - var_value_map.Bind(LoadMap(maybe_receiver)); - Node* const value_instance_type = LoadMapInstanceType(var_value_map.value()); - - Branch(IsJSReceiverInstanceType(value_instance_type), &out, &throw_exception); - - // The {value} is not a compatible receiver for this method. - BIND(&throw_exception); - { - Node* const value_str = - CallBuiltin(Builtins::kToString, context, maybe_receiver); - ThrowTypeError(context, msg_template, StringConstant(method_name), - value_str); - } - - BIND(&out); - return var_value_map.value(); +TNode<BoolT> RegExpBuiltinsAssembler::IsReceiverInitialRegExpPrototype( + SloppyTNode<Context> context, SloppyTNode<Object> receiver) { + TNode<NativeContext> native_context = LoadNativeContext(context); + TNode<JSFunction> const regexp_fun = + CAST(LoadContextElement(native_context, Context::REGEXP_FUNCTION_INDEX)); + TNode<Object> const initial_map = + LoadObjectField(regexp_fun, JSFunction::kPrototypeOrInitialMapOffset); + TNode<HeapObject> const initial_prototype = + LoadMapPrototype(CAST(initial_map)); + return TaggedEqual(receiver, initial_prototype); } -Node* RegExpBuiltinsAssembler::IsFastRegExpNoPrototype(Node* const context, - Node* const object, - Node* const map) { +Node* RegExpBuiltinsAssembler::IsFastRegExpNoPrototype( + SloppyTNode<Context> context, SloppyTNode<Object> object, + SloppyTNode<Map> map) { Label out(this); VARIABLE(var_result, MachineRepresentation::kWord32); @@ -843,12 +905,12 @@ Node* RegExpBuiltinsAssembler::IsFastRegExpNoPrototype(Node* const context, GotoIfForceSlowPath(&out); #endif - Node* const native_context = LoadNativeContext(context); - Node* const regexp_fun = - LoadContextElement(native_context, Context::REGEXP_FUNCTION_INDEX); - Node* const initial_map = + TNode<NativeContext> const native_context = LoadNativeContext(context); + TNode<HeapObject> const regexp_fun = + CAST(LoadContextElement(native_context, Context::REGEXP_FUNCTION_INDEX)); + TNode<Object> const initial_map = LoadObjectField(regexp_fun, JSFunction::kPrototypeOrInitialMapOffset); - Node* const has_initialmap = WordEqual(map, initial_map); + TNode<BoolT> const has_initialmap = TaggedEqual(map, initial_map); var_result.Bind(has_initialmap); GotoIfNot(has_initialmap, &out); @@ -882,14 +944,14 @@ TNode<BoolT> RegExpBuiltinsAssembler::IsFastRegExpWithOriginalExec( var_result = is_regexp; GotoIfNot(is_regexp, &out); - TNode<Context> native_context = LoadNativeContext(context); + TNode<NativeContext> native_context = LoadNativeContext(context); TNode<Object> original_exec = LoadContextElement(native_context, Context::REGEXP_EXEC_FUNCTION_INDEX); TNode<Object> regexp_exec = GetProperty(context, object, isolate()->factory()->exec_string()); - TNode<BoolT> has_initialexec = WordEqual(regexp_exec, original_exec); + TNode<BoolT> has_initialexec = TaggedEqual(regexp_exec, original_exec); var_result = has_initialexec; GotoIf(has_initialexec, &check_last_index); TNode<BoolT> is_undefined = IsUndefined(regexp_exec); @@ -908,85 +970,80 @@ TNode<BoolT> RegExpBuiltinsAssembler::IsFastRegExpWithOriginalExec( return var_result.value(); } -Node* RegExpBuiltinsAssembler::IsFastRegExpNoPrototype(Node* const context, - Node* const object) { +Node* RegExpBuiltinsAssembler::IsFastRegExpNoPrototype( + SloppyTNode<Context> context, SloppyTNode<Object> object) { CSA_ASSERT(this, TaggedIsNotSmi(object)); - return IsFastRegExpNoPrototype(context, object, LoadMap(object)); + return IsFastRegExpNoPrototype(context, object, LoadMap(CAST(object))); } -// RegExp fast path implementations rely on unmodified JSRegExp instances. -// We use a fairly coarse granularity for this and simply check whether both -// the regexp itself is unmodified (i.e. its map has not changed), its -// prototype is unmodified, and lastIndex is a non-negative smi. void RegExpBuiltinsAssembler::BranchIfFastRegExp( - Node* const context, Node* const object, Node* const map, - base::Optional<DescriptorIndexAndName> additional_property_to_check, - Label* const if_isunmodified, Label* const if_ismodified) { - CSA_ASSERT(this, WordEqual(LoadMap(object), map)); + TNode<Context> context, TNode<HeapObject> object, TNode<Map> map, + PrototypeCheckAssembler::Flags prototype_check_flags, + base::Optional<DescriptorIndexNameValue> additional_property_to_check, + Label* if_isunmodified, Label* if_ismodified) { + CSA_ASSERT(this, TaggedEqual(LoadMap(object), map)); GotoIfForceSlowPath(if_ismodified); // This should only be needed for String.p.(split||matchAll), but we are // conservative here. - TNode<Context> native_context = LoadNativeContext(context); + // Note: we are using the current native context here, which may or may not + // match the object's native context. That's fine: in case of a mismatch, we + // will bail in the next step when comparing the object's map against the + // current native context's initial regexp map. + TNode<NativeContext> native_context = LoadNativeContext(context); GotoIf(IsRegExpSpeciesProtectorCellInvalid(native_context), if_ismodified); - Node* const regexp_fun = - LoadContextElement(native_context, Context::REGEXP_FUNCTION_INDEX); - Node* const initial_map = - LoadObjectField(regexp_fun, JSFunction::kPrototypeOrInitialMapOffset); - Node* const has_initialmap = WordEqual(map, initial_map); + TNode<JSFunction> regexp_fun = + CAST(LoadContextElement(native_context, Context::REGEXP_FUNCTION_INDEX)); + TNode<Map> initial_map = CAST( + LoadObjectField(regexp_fun, JSFunction::kPrototypeOrInitialMapOffset)); + TNode<BoolT> has_initialmap = TaggedEqual(map, initial_map); GotoIfNot(has_initialmap, if_ismodified); - Node* const initial_proto_initial_map = - LoadContextElement(native_context, Context::REGEXP_PROTOTYPE_MAP_INDEX); + // The smi check is required to omit ToLength(lastIndex) calls with possible + // user-code execution on the fast path. + TNode<Object> last_index = FastLoadLastIndexBeforeSmiCheck(CAST(object)); + GotoIfNot(TaggedIsPositiveSmi(last_index), if_ismodified); + + // Verify the prototype. + + TNode<Map> initial_proto_initial_map = CAST( + LoadContextElement(native_context, Context::REGEXP_PROTOTYPE_MAP_INDEX)); - DescriptorIndexAndName properties_to_check[2]; + DescriptorIndexNameValue properties_to_check[2]; int property_count = 0; - properties_to_check[property_count++] = DescriptorIndexAndName{ - JSRegExp::kExecFunctionDescriptorIndex, RootIndex::kexec_string}; + properties_to_check[property_count++] = DescriptorIndexNameValue{ + JSRegExp::kExecFunctionDescriptorIndex, RootIndex::kexec_string, + Context::REGEXP_EXEC_FUNCTION_INDEX}; if (additional_property_to_check) { properties_to_check[property_count++] = *additional_property_to_check; } - GotoIfInitialPrototypePropertiesModified( - CAST(map), CAST(initial_proto_initial_map), - Vector<DescriptorIndexAndName>(properties_to_check, property_count), - if_ismodified); + PrototypeCheckAssembler prototype_check_assembler( + state(), prototype_check_flags, native_context, initial_proto_initial_map, + Vector<DescriptorIndexNameValue>(properties_to_check, property_count)); - // The smi check is required to omit ToLength(lastIndex) calls with possible - // user-code execution on the fast path. - TNode<Object> last_index = FastLoadLastIndexBeforeSmiCheck(CAST(object)); - Branch(TaggedIsPositiveSmi(last_index), if_isunmodified, if_ismodified); + TNode<HeapObject> prototype = LoadMapPrototype(map); + prototype_check_assembler.CheckAndBranch(prototype, if_isunmodified, + if_ismodified); } -void RegExpBuiltinsAssembler::BranchIfFastRegExp(Node* const context, - Node* const object, - Label* const if_isunmodified, - Label* const if_ismodified) { - CSA_ASSERT(this, TaggedIsNotSmi(object)); - BranchIfFastRegExp(context, object, LoadMap(object), base::nullopt, - if_isunmodified, if_ismodified); +void RegExpBuiltinsAssembler::BranchIfFastRegExp_Strict( + TNode<Context> context, TNode<HeapObject> object, Label* if_isunmodified, + Label* if_ismodified) { + BranchIfFastRegExp(context, object, LoadMap(object), + PrototypeCheckAssembler::kCheckPrototypePropertyConstness, + base::nullopt, if_isunmodified, if_ismodified); } -TNode<BoolT> RegExpBuiltinsAssembler::IsFastRegExp(SloppyTNode<Context> context, - SloppyTNode<Object> object) { - Label yup(this), nope(this), out(this); - TVARIABLE(BoolT, var_result); - - BranchIfFastRegExp(context, object, &yup, &nope); - - BIND(&yup); - var_result = Int32TrueConstant(); - Goto(&out); - - BIND(&nope); - var_result = Int32FalseConstant(); - Goto(&out); - - BIND(&out); - return var_result.value(); +void RegExpBuiltinsAssembler::BranchIfFastRegExp_Permissive( + TNode<Context> context, TNode<HeapObject> object, Label* if_isunmodified, + Label* if_ismodified) { + BranchIfFastRegExp(context, object, LoadMap(object), + PrototypeCheckAssembler::kCheckFull, base::nullopt, + if_isunmodified, if_ismodified); } void RegExpBuiltinsAssembler::BranchIfFastRegExpResult(Node* const context, @@ -994,13 +1051,13 @@ void RegExpBuiltinsAssembler::BranchIfFastRegExpResult(Node* const context, Label* if_isunmodified, Label* if_ismodified) { // Could be a Smi. - Node* const map = LoadReceiverMap(object); + TNode<Map> const map = LoadReceiverMap(object); - Node* const native_context = LoadNativeContext(context); - Node* const initial_regexp_result_map = + TNode<NativeContext> const native_context = LoadNativeContext(context); + TNode<Object> const initial_regexp_result_map = LoadContextElement(native_context, Context::REGEXP_RESULT_MAP_INDEX); - Branch(WordEqual(map, initial_regexp_result_map), if_isunmodified, + Branch(TaggedEqual(map, initial_regexp_result_map), if_isunmodified, if_ismodified); } @@ -1036,9 +1093,8 @@ TF_BUILTIN(RegExpExecAtom, RegExpBuiltinsAssembler) { UintPtrLessThanOrEqual(SmiUntag(last_index), LoadStringLengthAsWord(subject_string))); - Node* const needle_string = - UnsafeLoadFixedArrayElement(data, JSRegExp::kAtomPatternIndex); - CSA_ASSERT(this, IsString(needle_string)); + TNode<String> const needle_string = + CAST(UnsafeLoadFixedArrayElement(data, JSRegExp::kAtomPatternIndex)); TNode<Smi> const match_from = CAST(CallBuiltin(Builtins::kStringIndexOf, context, subject_string, @@ -1120,9 +1176,9 @@ TF_BUILTIN(RegExpPrototypeExec, RegExpBuiltinsAssembler) { string)); } -Node* RegExpBuiltinsAssembler::FlagsGetter(Node* const context, - Node* const regexp, - bool is_fastpath) { +TNode<String> RegExpBuiltinsAssembler::FlagsGetter(TNode<Context> context, + TNode<Object> regexp, + bool is_fastpath) { Isolate* isolate = this->isolate(); TNode<IntPtrT> const int_one = IntPtrConstant(1); @@ -1134,8 +1190,9 @@ Node* RegExpBuiltinsAssembler::FlagsGetter(Node* const context, if (is_fastpath) { // Refer to JSRegExp's flag property on the fast-path. - CSA_ASSERT(this, IsJSRegExp(regexp)); - Node* const flags_smi = LoadObjectField(regexp, JSRegExp::kFlagsOffset); + CSA_ASSERT(this, IsJSRegExp(CAST(regexp))); + TNode<Smi> const flags_smi = + CAST(LoadObjectField(CAST(regexp), JSRegExp::kFlagsOffset)); var_flags = SmiUntag(flags_smi); #define CASE_FOR_FLAG(FLAG) \ @@ -1163,7 +1220,7 @@ Node* RegExpBuiltinsAssembler::FlagsGetter(Node* const context, #define CASE_FOR_FLAG(NAME, FLAG) \ do { \ Label next(this); \ - Node* const flag = GetProperty( \ + TNode<Object> const flag = GetProperty( \ context, regexp, isolate->factory()->InternalizeUtf8String(NAME)); \ Label if_isflagset(this); \ BranchIfToBooleanIsTrue(flag, &if_isflagset, &next); \ @@ -1187,7 +1244,7 @@ Node* RegExpBuiltinsAssembler::FlagsGetter(Node* const context, // char for each set flag. { - Node* const result = AllocateSeqOneByteString(context, var_length.value()); + TNode<String> const result = AllocateSeqOneByteString(var_length.value()); VARIABLE(var_offset, MachineType::PointerRepresentation(), IntPtrConstant(SeqOneByteString::kHeaderSize - kHeapObjectTag)); @@ -1196,7 +1253,7 @@ Node* RegExpBuiltinsAssembler::FlagsGetter(Node* const context, do { \ Label next(this); \ GotoIfNot(IsSetWord(var_flags.value(), FLAG), &next); \ - Node* const value = Int32Constant(CHAR); \ + TNode<Int32T> const value = Int32Constant(CHAR); \ StoreNoWriteBarrier(MachineRepresentation::kWord8, result, \ var_offset.value(), value); \ var_offset.Bind(IntPtrAdd(var_offset.value(), int_one)); \ @@ -1290,27 +1347,6 @@ Node* RegExpBuiltinsAssembler::RegExpInitialize(Node* const context, pattern, flags); } -// ES #sec-get-regexp.prototype.flags -TF_BUILTIN(RegExpPrototypeFlagsGetter, RegExpBuiltinsAssembler) { - TNode<Object> maybe_receiver = CAST(Parameter(Descriptor::kReceiver)); - TNode<Context> context = CAST(Parameter(Descriptor::kContext)); - - TNode<Map> map = CAST(ThrowIfNotJSReceiver(context, maybe_receiver, - MessageTemplate::kRegExpNonObject, - "RegExp.prototype.flags")); - TNode<JSReceiver> receiver = CAST(maybe_receiver); - - Label if_isfastpath(this), if_isslowpath(this, Label::kDeferred); - BranchIfFastRegExp(context, receiver, map, base::nullopt, &if_isfastpath, - &if_isslowpath); - - BIND(&if_isfastpath); - Return(FlagsGetter(context, receiver, true)); - - BIND(&if_isslowpath); - Return(FlagsGetter(context, receiver, false)); -} - // ES#sec-regexp-pattern-flags // RegExp ( pattern, flags ) TF_BUILTIN(RegExpConstructor, RegExpBuiltinsAssembler) { @@ -1321,13 +1357,13 @@ TF_BUILTIN(RegExpConstructor, RegExpBuiltinsAssembler) { Isolate* isolate = this->isolate(); - VARIABLE(var_flags, MachineRepresentation::kTagged, flags); - VARIABLE(var_pattern, MachineRepresentation::kTagged, pattern); - VARIABLE(var_new_target, MachineRepresentation::kTagged, new_target); + TVARIABLE(Object, var_flags, flags); + TVARIABLE(Object, var_pattern, pattern); + TVARIABLE(Object, var_new_target, new_target); - Node* const native_context = LoadNativeContext(context); - Node* const regexp_function = - LoadContextElement(native_context, Context::REGEXP_FUNCTION_INDEX); + TNode<NativeContext> native_context = LoadNativeContext(context); + TNode<JSFunction> regexp_function = + CAST(LoadContextElement(native_context, Context::REGEXP_FUNCTION_INDEX)); TNode<BoolT> pattern_is_regexp = IsRegExp(context, pattern); @@ -1335,15 +1371,15 @@ TF_BUILTIN(RegExpConstructor, RegExpBuiltinsAssembler) { Label next(this); GotoIfNot(IsUndefined(new_target), &next); - var_new_target.Bind(regexp_function); + var_new_target = regexp_function; GotoIfNot(pattern_is_regexp, &next); GotoIfNot(IsUndefined(flags), &next); - Node* const value = + TNode<Object> value = GetProperty(context, pattern, isolate->factory()->constructor_string()); - GotoIfNot(WordEqual(value, regexp_function), &next); + GotoIfNot(TaggedEqual(value, regexp_function), &next); Return(pattern); BIND(&next); @@ -1360,16 +1396,15 @@ TF_BUILTIN(RegExpConstructor, RegExpBuiltinsAssembler) { BIND(&if_patternisfastregexp); { - Node* const source = + TNode<Object> source = LoadObjectField(CAST(pattern), JSRegExp::kSourceOffset); - var_pattern.Bind(source); + var_pattern = source; { Label inner_next(this); GotoIfNot(IsUndefined(flags), &inner_next); - Node* const value = FlagsGetter(context, pattern, true); - var_flags.Bind(value); + var_flags = FlagsGetter(context, pattern, true); Goto(&inner_next); BIND(&inner_next); @@ -1380,19 +1415,15 @@ TF_BUILTIN(RegExpConstructor, RegExpBuiltinsAssembler) { BIND(&if_patternisslowregexp); { - { - Node* const value = - GetProperty(context, pattern, isolate->factory()->source_string()); - var_pattern.Bind(value); - } + var_pattern = + GetProperty(context, pattern, isolate->factory()->source_string()); { Label inner_next(this); GotoIfNot(IsUndefined(flags), &inner_next); - Node* const value = + var_flags = GetProperty(context, pattern, isolate->factory()->flags_string()); - var_flags.Bind(value); Goto(&inner_next); BIND(&inner_next); @@ -1410,14 +1441,14 @@ TF_BUILTIN(RegExpConstructor, RegExpBuiltinsAssembler) { { Label allocate_jsregexp(this), allocate_generic(this, Label::kDeferred), next(this); - Branch(WordEqual(var_new_target.value(), regexp_function), + Branch(TaggedEqual(var_new_target.value(), regexp_function), &allocate_jsregexp, &allocate_generic); BIND(&allocate_jsregexp); { - Node* const initial_map = LoadObjectField( - regexp_function, JSFunction::kPrototypeOrInitialMapOffset); - Node* const regexp = AllocateJSObjectFromMap(initial_map); + TNode<Map> const initial_map = CAST(LoadObjectField( + regexp_function, JSFunction::kPrototypeOrInitialMapOffset)); + TNode<JSObject> const regexp = AllocateJSObjectFromMap(initial_map); var_regexp.Bind(regexp); Goto(&next); } @@ -1425,8 +1456,8 @@ TF_BUILTIN(RegExpConstructor, RegExpBuiltinsAssembler) { BIND(&allocate_generic); { ConstructorBuiltinsAssembler constructor_assembler(this->state()); - Node* const regexp = constructor_assembler.EmitFastNewObject( - context, regexp_function, var_new_target.value()); + TNode<JSObject> const regexp = constructor_assembler.EmitFastNewObject( + context, regexp_function, CAST(var_new_target.value())); var_regexp.Bind(regexp); Goto(&next); } @@ -1473,8 +1504,9 @@ TF_BUILTIN(RegExpPrototypeCompile, RegExpBuiltinsAssembler) { BIND(&next); } - Node* const new_flags = FlagsGetter(context, pattern, true); - Node* const new_pattern = LoadObjectField(pattern, JSRegExp::kSourceOffset); + TNode<String> const new_flags = FlagsGetter(context, CAST(pattern), true); + TNode<Object> const new_pattern = + LoadObjectField(pattern, JSRegExp::kSourceOffset); var_flags.Bind(new_flags); var_pattern.Bind(new_pattern); @@ -1488,69 +1520,22 @@ TF_BUILTIN(RegExpPrototypeCompile, RegExpBuiltinsAssembler) { Return(result); } -// ES6 21.2.5.10. -// ES #sec-get-regexp.prototype.source -TF_BUILTIN(RegExpPrototypeSourceGetter, RegExpBuiltinsAssembler) { - TNode<Object> receiver = CAST(Parameter(Descriptor::kReceiver)); - TNode<Context> context = CAST(Parameter(Descriptor::kContext)); - - // Check whether we have an unmodified regexp instance. - Label if_isjsregexp(this), if_isnotjsregexp(this, Label::kDeferred); - - GotoIf(TaggedIsSmi(receiver), &if_isnotjsregexp); - Branch(IsJSRegExp(CAST(receiver)), &if_isjsregexp, &if_isnotjsregexp); - - BIND(&if_isjsregexp); - Return(LoadObjectField(CAST(receiver), JSRegExp::kSourceOffset)); - - BIND(&if_isnotjsregexp); - { - Isolate* isolate = this->isolate(); - Node* const native_context = LoadNativeContext(context); - Node* const regexp_fun = - LoadContextElement(native_context, Context::REGEXP_FUNCTION_INDEX); - Node* const initial_map = - LoadObjectField(regexp_fun, JSFunction::kPrototypeOrInitialMapOffset); - Node* const initial_prototype = LoadMapPrototype(initial_map); - - Label if_isprototype(this), if_isnotprototype(this); - Branch(WordEqual(receiver, initial_prototype), &if_isprototype, - &if_isnotprototype); - - BIND(&if_isprototype); - { - const int counter = v8::Isolate::kRegExpPrototypeSourceGetter; - Node* const counter_smi = SmiConstant(counter); - CallRuntime(Runtime::kIncrementUseCounter, context, counter_smi); - - Node* const result = - HeapConstant(isolate->factory()->NewStringFromAsciiChecked("(?:)")); - Return(result); - } - - BIND(&if_isnotprototype); - { - ThrowTypeError(context, MessageTemplate::kRegExpNonRegExp, - "RegExp.prototype.source"); - } - } -} - // Fast-path implementation for flag checks on an unmodified JSRegExp instance. -TNode<Int32T> RegExpBuiltinsAssembler::FastFlagGetter(TNode<JSRegExp> regexp, - JSRegExp::Flag flag) { +TNode<BoolT> RegExpBuiltinsAssembler::FastFlagGetter(TNode<JSRegExp> regexp, + JSRegExp::Flag flag) { TNode<Smi> flags = CAST(LoadObjectField(regexp, JSRegExp::kFlagsOffset)); TNode<Smi> mask = SmiConstant(flag); - return SmiToInt32(SmiShr(SmiAnd(flags, mask), base::bits::CountTrailingZeros( - static_cast<int>(flag)))); + return ReinterpretCast<BoolT>(SmiToInt32( + SmiShr(SmiAnd(flags, mask), + base::bits::CountTrailingZeros(static_cast<int>(flag))))); } // Load through the GetProperty stub. -TNode<Int32T> RegExpBuiltinsAssembler::SlowFlagGetter(TNode<Context> context, - TNode<Object> regexp, - JSRegExp::Flag flag) { +TNode<BoolT> RegExpBuiltinsAssembler::SlowFlagGetter(TNode<Context> context, + TNode<Object> regexp, + JSRegExp::Flag flag) { Label out(this); - TVARIABLE(Int32T, var_result); + TVARIABLE(BoolT, var_result); Handle<String> name; switch (flag) { @@ -1582,140 +1567,36 @@ TNode<Int32T> RegExpBuiltinsAssembler::SlowFlagGetter(TNode<Context> context, BranchIfToBooleanIsTrue(value, &if_true, &if_false); BIND(&if_true); - var_result = Int32Constant(1); + var_result = BoolConstant(true); Goto(&out); BIND(&if_false); - var_result = Int32Constant(0); + var_result = BoolConstant(false); Goto(&out); BIND(&out); return var_result.value(); } -TNode<Int32T> RegExpBuiltinsAssembler::FlagGetter(TNode<Context> context, - TNode<Object> regexp, - JSRegExp::Flag flag, - bool is_fastpath) { +TNode<BoolT> RegExpBuiltinsAssembler::FlagGetter(TNode<Context> context, + TNode<Object> regexp, + JSRegExp::Flag flag, + bool is_fastpath) { return is_fastpath ? FastFlagGetter(CAST(regexp), flag) : SlowFlagGetter(context, regexp, flag); } -void RegExpBuiltinsAssembler::FlagGetter(Node* context, Node* receiver, - JSRegExp::Flag flag, int counter, - const char* method_name) { - // Check whether we have an unmodified regexp instance. - Label if_isunmodifiedjsregexp(this), - if_isnotunmodifiedjsregexp(this, Label::kDeferred); - - GotoIf(TaggedIsSmi(receiver), &if_isnotunmodifiedjsregexp); - Branch(IsJSRegExp(receiver), &if_isunmodifiedjsregexp, - &if_isnotunmodifiedjsregexp); - - BIND(&if_isunmodifiedjsregexp); - { - // Refer to JSRegExp's flag property on the fast-path. - Node* const is_flag_set = FastFlagGetter(CAST(receiver), flag); - Return(SelectBooleanConstant(is_flag_set)); - } - - BIND(&if_isnotunmodifiedjsregexp); - { - Node* const native_context = LoadNativeContext(context); - Node* const regexp_fun = - LoadContextElement(native_context, Context::REGEXP_FUNCTION_INDEX); - Node* const initial_map = - LoadObjectField(regexp_fun, JSFunction::kPrototypeOrInitialMapOffset); - Node* const initial_prototype = LoadMapPrototype(initial_map); - - Label if_isprototype(this), if_isnotprototype(this); - Branch(WordEqual(receiver, initial_prototype), &if_isprototype, - &if_isnotprototype); - - BIND(&if_isprototype); - { - if (counter != -1) { - Node* const counter_smi = SmiConstant(counter); - CallRuntime(Runtime::kIncrementUseCounter, context, counter_smi); - } - Return(UndefinedConstant()); - } - - BIND(&if_isnotprototype); - { ThrowTypeError(context, MessageTemplate::kRegExpNonRegExp, method_name); } - } -} - -// ES6 21.2.5.4. -// ES #sec-get-regexp.prototype.global -TF_BUILTIN(RegExpPrototypeGlobalGetter, RegExpBuiltinsAssembler) { - TNode<Context> context = CAST(Parameter(Descriptor::kContext)); - TNode<Object> receiver = CAST(Parameter(Descriptor::kReceiver)); - FlagGetter(context, receiver, JSRegExp::kGlobal, - v8::Isolate::kRegExpPrototypeOldFlagGetter, - "RegExp.prototype.global"); -} - -// ES6 21.2.5.5. -// ES #sec-get-regexp.prototype.ignorecase -TF_BUILTIN(RegExpPrototypeIgnoreCaseGetter, RegExpBuiltinsAssembler) { - TNode<Context> context = CAST(Parameter(Descriptor::kContext)); - TNode<Object> receiver = CAST(Parameter(Descriptor::kReceiver)); - FlagGetter(context, receiver, JSRegExp::kIgnoreCase, - v8::Isolate::kRegExpPrototypeOldFlagGetter, - "RegExp.prototype.ignoreCase"); -} - -// ES6 21.2.5.7. -// ES #sec-get-regexp.prototype.multiline -TF_BUILTIN(RegExpPrototypeMultilineGetter, RegExpBuiltinsAssembler) { - TNode<Context> context = CAST(Parameter(Descriptor::kContext)); - TNode<Object> receiver = CAST(Parameter(Descriptor::kReceiver)); - FlagGetter(context, receiver, JSRegExp::kMultiline, - v8::Isolate::kRegExpPrototypeOldFlagGetter, - "RegExp.prototype.multiline"); -} - -// ES #sec-get-regexp.prototype.dotAll -TF_BUILTIN(RegExpPrototypeDotAllGetter, RegExpBuiltinsAssembler) { - TNode<Context> context = CAST(Parameter(Descriptor::kContext)); - TNode<Object> receiver = CAST(Parameter(Descriptor::kReceiver)); - static const int kNoCounter = -1; - FlagGetter(context, receiver, JSRegExp::kDotAll, kNoCounter, - "RegExp.prototype.dotAll"); -} - -// ES6 21.2.5.12. -// ES #sec-get-regexp.prototype.sticky -TF_BUILTIN(RegExpPrototypeStickyGetter, RegExpBuiltinsAssembler) { - TNode<Context> context = CAST(Parameter(Descriptor::kContext)); - TNode<Object> receiver = CAST(Parameter(Descriptor::kReceiver)); - FlagGetter(context, receiver, JSRegExp::kSticky, - v8::Isolate::kRegExpPrototypeStickyGetter, - "RegExp.prototype.sticky"); -} - -// ES6 21.2.5.15. -// ES #sec-get-regexp.prototype.unicode -TF_BUILTIN(RegExpPrototypeUnicodeGetter, RegExpBuiltinsAssembler) { - TNode<Context> context = CAST(Parameter(Descriptor::kContext)); - TNode<Object> receiver = CAST(Parameter(Descriptor::kReceiver)); - FlagGetter(context, receiver, JSRegExp::kUnicode, - v8::Isolate::kRegExpPrototypeUnicodeGetter, - "RegExp.prototype.unicode"); -} - // ES#sec-regexpexec Runtime Semantics: RegExpExec ( R, S ) -Node* RegExpBuiltinsAssembler::RegExpExec(Node* context, Node* regexp, - Node* string) { - VARIABLE(var_result, MachineRepresentation::kTagged); +TNode<Object> RegExpBuiltinsAssembler::RegExpExec(TNode<Context> context, + Node* regexp, Node* string) { + TVARIABLE(Object, var_result); Label out(this); // Take the slow path of fetching the exec property, calling it, and // verifying its return value. // Get the exec property. - Node* const exec = + TNode<Object> const exec = GetProperty(context, regexp, isolate()->factory()->exec_string()); // Is {exec} callable? @@ -1723,18 +1604,17 @@ Node* RegExpBuiltinsAssembler::RegExpExec(Node* context, Node* regexp, GotoIf(TaggedIsSmi(exec), &if_isnotcallable); - Node* const exec_map = LoadMap(exec); + TNode<Map> const exec_map = LoadMap(CAST(exec)); Branch(IsCallableMap(exec_map), &if_iscallable, &if_isnotcallable); BIND(&if_iscallable); { Callable call_callable = CodeFactory::Call(isolate()); - Node* const result = CallJS(call_callable, context, exec, regexp, string); + var_result = CAST(CallJS(call_callable, context, exec, regexp, string)); - var_result.Bind(result); - GotoIf(IsNull(result), &out); + GotoIf(IsNull(var_result.value()), &out); - ThrowIfNotJSReceiver(context, result, + ThrowIfNotJSReceiver(context, var_result.value(), MessageTemplate::kInvalidRegExpExecResult, ""); Goto(&out); @@ -1745,9 +1625,8 @@ Node* RegExpBuiltinsAssembler::RegExpExec(Node* context, Node* regexp, ThrowIfNotInstanceType(context, regexp, JS_REGEXP_TYPE, "RegExp.prototype.exec"); - Node* const result = CallBuiltin(Builtins::kRegExpPrototypeExecSlow, - context, regexp, string); - var_result.Bind(result); + var_result = CallBuiltin(Builtins::kRegExpPrototypeExecSlow, context, + regexp, string); Goto(&out); } @@ -1755,62 +1634,6 @@ Node* RegExpBuiltinsAssembler::RegExpExec(Node* context, Node* regexp, return var_result.value(); } -// ES#sec-regexp.prototype.test -// RegExp.prototype.test ( S ) -TF_BUILTIN(RegExpPrototypeTest, RegExpBuiltinsAssembler) { - TNode<Object> maybe_receiver = CAST(Parameter(Descriptor::kReceiver)); - TNode<Object> maybe_string = CAST(Parameter(Descriptor::kString)); - TNode<Context> context = CAST(Parameter(Descriptor::kContext)); - - // Ensure {maybe_receiver} is a JSReceiver. - ThrowIfNotJSReceiver(context, maybe_receiver, - MessageTemplate::kIncompatibleMethodReceiver, - "RegExp.prototype.test"); - TNode<JSReceiver> receiver = CAST(maybe_receiver); - - // Convert {maybe_string} to a String. - TNode<String> string = ToString_Inline(context, maybe_string); - - Label fast_path(this), slow_path(this); - BranchIfFastRegExp(context, receiver, &fast_path, &slow_path); - - BIND(&fast_path); - { - Label if_didnotmatch(this); - RegExpPrototypeExecBodyWithoutResult(context, receiver, string, - &if_didnotmatch, true); - Return(TrueConstant()); - - BIND(&if_didnotmatch); - Return(FalseConstant()); - } - - BIND(&slow_path); - { - // Call exec. - TNode<HeapObject> match_indices = - CAST(RegExpExec(context, receiver, string)); - - // Return true iff exec matched successfully. - Return(SelectBooleanConstant(IsNotNull(match_indices))); - } -} - -TF_BUILTIN(RegExpPrototypeTestFast, RegExpBuiltinsAssembler) { - TNode<JSRegExp> regexp = CAST(Parameter(Descriptor::kReceiver)); - TNode<String> string = CAST(Parameter(Descriptor::kString)); - TNode<Context> context = CAST(Parameter(Descriptor::kContext)); - - Label if_didnotmatch(this); - CSA_ASSERT(this, IsFastRegExpWithOriginalExec(context, regexp)); - RegExpPrototypeExecBodyWithoutResult(context, regexp, string, &if_didnotmatch, - true); - Return(TrueConstant()); - - BIND(&if_didnotmatch); - Return(FalseConstant()); -} - TNode<Number> RegExpBuiltinsAssembler::AdvanceStringIndex( SloppyTNode<String> string, SloppyTNode<Number> index, SloppyTNode<BoolT> is_unicode, bool is_fastpath) { @@ -1852,12 +1675,12 @@ TNode<Number> RegExpBuiltinsAssembler::AdvanceStringIndex( TNode<IntPtrT> untagged_plus_one = SmiUntag(CAST(index_plus_one)); GotoIfNot(IntPtrLessThan(untagged_plus_one, string_length), &out); - Node* const lead = StringCharCodeAt(string, SmiUntag(CAST(index))); + TNode<Int32T> const lead = StringCharCodeAt(string, SmiUntag(CAST(index))); GotoIfNot(Word32Equal(Word32And(lead, Int32Constant(0xFC00)), Int32Constant(0xD800)), &out); - Node* const trail = StringCharCodeAt(string, untagged_plus_one); + TNode<Int32T> const trail = StringCharCodeAt(string, untagged_plus_one); GotoIfNot(Word32Equal(Word32And(trail, Int32Constant(0xFC00)), Int32Constant(0xDC00)), &out); @@ -1873,29 +1696,34 @@ TNode<Number> RegExpBuiltinsAssembler::AdvanceStringIndex( return var_result.value(); } -void RegExpBuiltinsAssembler::RegExpPrototypeMatchBody(TNode<Context> context, - TNode<Object> regexp, - TNode<String> string, - const bool is_fastpath) { - if (is_fastpath) CSA_ASSERT(this, IsFastRegExp(context, regexp)); +TNode<Object> RegExpBuiltinsAssembler::RegExpPrototypeMatchBody( + TNode<Context> context, TNode<Object> regexp, TNode<String> string, + const bool is_fastpath) { + if (is_fastpath) { + CSA_ASSERT_BRANCH(this, [&](Label* ok, Label* not_ok) { + BranchIfFastRegExp_Strict(context, CAST(regexp), ok, not_ok); + }); + } - Node* const is_global = + TVARIABLE(Object, var_result); + + TNode<BoolT> const is_global = FlagGetter(context, regexp, JSRegExp::kGlobal, is_fastpath); - Label if_isglobal(this), if_isnotglobal(this); + Label if_isglobal(this), if_isnotglobal(this), done(this); Branch(is_global, &if_isglobal, &if_isnotglobal); BIND(&if_isnotglobal); { - Node* const result = is_fastpath ? RegExpPrototypeExecBody( - context, CAST(regexp), string, true) - : RegExpExec(context, regexp, string); - Return(result); + var_result = is_fastpath ? RegExpPrototypeExecBody(context, CAST(regexp), + string, true) + : RegExpExec(context, regexp, string); + Goto(&done); } BIND(&if_isglobal); { - Node* const is_unicode = + TNode<BoolT> const is_unicode = FlagGetter(context, regexp, JSRegExp::kUnicode, is_fastpath); StoreLastIndex(context, regexp, SmiZero(), is_fastpath); @@ -1939,15 +1767,14 @@ void RegExpBuiltinsAssembler::RegExpPrototypeMatchBody(TNode<Context> context, TNode<RegExpMatchInfo> match_indices = RegExpPrototypeExecBodyWithoutResult(context, CAST(regexp), string, &if_didnotmatch, true); - Label dosubstring(this), donotsubstring(this); Branch(var_atom.value(), &donotsubstring, &dosubstring); BIND(&dosubstring); { - Node* const match_from = UnsafeLoadFixedArrayElement( + TNode<Object> const match_from = UnsafeLoadFixedArrayElement( match_indices, RegExpMatchInfo::kFirstCaptureIndex); - Node* const match_to = UnsafeLoadFixedArrayElement( + TNode<Object> const match_to = UnsafeLoadFixedArrayElement( match_indices, RegExpMatchInfo::kFirstCaptureIndex + 1); var_match.Bind(CallBuiltin(Builtins::kSubString, context, string, match_from, match_to)); @@ -1959,7 +1786,7 @@ void RegExpBuiltinsAssembler::RegExpPrototypeMatchBody(TNode<Context> context, Goto(&if_didmatch); } else { DCHECK(!is_fastpath); - Node* const result = RegExpExec(context, regexp, string); + TNode<Object> const result = RegExpExec(context, regexp, string); Label load_match(this); Branch(IsNull(result), &if_didnotmatch, &load_match); @@ -1974,7 +1801,8 @@ void RegExpBuiltinsAssembler::RegExpPrototypeMatchBody(TNode<Context> context, { // Return null if there were no matches, otherwise just exit the loop. GotoIfNot(IntPtrEqual(array.length(), IntPtrZero()), &out); - Return(NullConstant()); + var_result = NullConstant(); + Goto(&done); } BIND(&if_didmatch); @@ -1990,15 +1818,15 @@ void RegExpBuiltinsAssembler::RegExpPrototypeMatchBody(TNode<Context> context, TNode<Smi> const match_length = LoadStringLengthAsSmi(match); GotoIfNot(SmiEqual(match_length, SmiZero()), &loop); - Node* last_index = LoadLastIndex(context, regexp, is_fastpath); + TNode<Object> last_index = LoadLastIndex(context, regexp, is_fastpath); if (is_fastpath) { CSA_ASSERT(this, TaggedIsPositiveSmi(last_index)); } else { last_index = ToLength_Inline(context, last_index); } - TNode<Number> new_last_index = - AdvanceStringIndex(string, last_index, is_unicode, is_fastpath); + TNode<Number> new_last_index = AdvanceStringIndex( + string, CAST(last_index), is_unicode, is_fastpath); if (is_fastpath) { // On the fast path, we can be certain that lastIndex can never be @@ -2018,38 +1846,13 @@ void RegExpBuiltinsAssembler::RegExpPrototypeMatchBody(TNode<Context> context, { // Wrap the match in a JSArray. - Node* const result = array.ToJSArray(context); - Return(result); + var_result = array.ToJSArray(context); + Goto(&done); } } -} - -// ES#sec-regexp.prototype-@@match -// RegExp.prototype [ @@match ] ( string ) -TF_BUILTIN(RegExpPrototypeMatch, RegExpBuiltinsAssembler) { - TNode<Object> maybe_receiver = CAST(Parameter(Descriptor::kReceiver)); - TNode<Object> maybe_string = CAST(Parameter(Descriptor::kString)); - TNode<Context> context = CAST(Parameter(Descriptor::kContext)); - // Ensure {maybe_receiver} is a JSReceiver. - ThrowIfNotJSReceiver(context, maybe_receiver, - MessageTemplate::kIncompatibleMethodReceiver, - "RegExp.prototype.@@match"); - TNode<JSReceiver> receiver = CAST(maybe_receiver); - - // Convert {maybe_string} to a String. - TNode<String> const string = ToString_Inline(context, maybe_string); - - Label fast_path(this), slow_path(this); - BranchIfFastRegExp(context, receiver, &fast_path, &slow_path); - - BIND(&fast_path); - // TODO(pwong): Could be optimized to remove the overhead of calling the - // builtin (at the cost of a larger builtin). - Return(CallBuiltin(Builtins::kRegExpMatchFast, context, receiver, string)); - - BIND(&slow_path); - RegExpPrototypeMatchBody(context, receiver, string, false); + BIND(&done); + return var_result.value(); } void RegExpMatchAllAssembler::Generate(TNode<Context> context, @@ -2066,12 +1869,17 @@ void RegExpMatchAllAssembler::Generate(TNode<Context> context, TNode<String> string = ToString_Inline(context, maybe_string); TVARIABLE(Object, var_matcher); - TVARIABLE(Int32T, var_global); - TVARIABLE(Int32T, var_unicode); + TVARIABLE(BoolT, var_global); + TVARIABLE(BoolT, var_unicode); Label create_iterator(this), if_fast_regexp(this), if_slow_regexp(this, Label::kDeferred); - BranchIfFastRegExp(context, receiver, &if_fast_regexp, &if_slow_regexp); + // Strict, because following code uses the flags property. + // TODO(jgruber): Handle slow flag accesses on the fast path and make this + // permissive. + BranchIfFastRegExp_Strict(context, CAST(receiver), &if_fast_regexp, + &if_slow_regexp); + BIND(&if_fast_regexp); { TNode<JSRegExp> fast_regexp = CAST(receiver); @@ -2081,9 +1889,10 @@ void RegExpMatchAllAssembler::Generate(TNode<Context> context, // 4. Let C be ? SpeciesConstructor(R, %RegExp%). // 5. Let flags be ? ToString(? Get(R, "flags")). // 6. Let matcher be ? Construct(C, « R, flags »). - TNode<String> flags = CAST(FlagsGetter(context, fast_regexp, true)); + TNode<String> flags = FlagsGetter(context, fast_regexp, true); var_matcher = RegExpCreate(context, native_context, source, flags); - CSA_ASSERT(this, IsFastRegExp(context, var_matcher.value())); + CSA_ASSERT(this, + IsFastRegExpPermissive(context, CAST(var_matcher.value()))); // 7. Let lastIndex be ? ToLength(? Get(R, "lastIndex")). // 8. Perform ? Set(matcher, "lastIndex", lastIndex, true). @@ -2130,8 +1939,7 @@ void RegExpMatchAllAssembler::Generate(TNode<Context> context, TNode<Smi> global_ix = CAST(CallBuiltin(Builtins::kStringIndexOf, context, flags_string, global_char_string, SmiZero())); - var_global = - SelectInt32Constant(SmiEqual(global_ix, SmiConstant(-1)), 0, 1); + var_global = SmiNotEqual(global_ix, SmiConstant(-1)); // 11. If flags contains "u", let fullUnicode be true. // 12. Else, let fullUnicode be false. @@ -2139,13 +1947,23 @@ void RegExpMatchAllAssembler::Generate(TNode<Context> context, TNode<Smi> unicode_ix = CAST(CallBuiltin(Builtins::kStringIndexOf, context, flags_string, unicode_char_string, SmiZero())); - var_unicode = - SelectInt32Constant(SmiEqual(unicode_ix, SmiConstant(-1)), 0, 1); + var_unicode = SmiNotEqual(unicode_ix, SmiConstant(-1)); Goto(&create_iterator); } BIND(&create_iterator); { + { + // UseCounter for matchAll with non-g RegExp. + // https://crbug.com/v8/9551 + Label next(this); + GotoIf(var_global.value(), &next); + CallRuntime(Runtime::kIncrementUseCounter, context, + SmiConstant(v8::Isolate::kRegExpMatchAllWithNonGlobalRegExp)); + Goto(&next); + BIND(&next); + } + // 13. Return ! CreateRegExpStringIterator(matcher, S, global, fullUnicode). TNode<Object> iterator = CreateRegExpStringIterator(native_context, var_matcher.value(), string, @@ -2158,7 +1976,7 @@ void RegExpMatchAllAssembler::Generate(TNode<Context> context, // CreateRegExpStringIterator ( R, S, global, fullUnicode ) TNode<Object> RegExpMatchAllAssembler::CreateRegExpStringIterator( TNode<Context> native_context, TNode<Object> regexp, TNode<String> string, - TNode<Int32T> global, TNode<Int32T> full_unicode) { + TNode<BoolT> global, TNode<BoolT> full_unicode) { TNode<Map> map = CAST(LoadContextElement( native_context, Context::INITIAL_REGEXP_STRING_ITERATOR_PROTOTYPE_MAP_INDEX)); @@ -2166,7 +1984,7 @@ TNode<Object> RegExpMatchAllAssembler::CreateRegExpStringIterator( // 4. Let iterator be ObjectCreate(%RegExpStringIteratorPrototype%, « // [[IteratingRegExp]], [[IteratedString]], [[Global]], [[Unicode]], // [[Done]] »). - TNode<Object> iterator = Allocate(JSRegExpStringIterator::kSize); + TNode<HeapObject> iterator = Allocate(JSRegExpStringIterator::kSize); StoreMapNoWriteBarrier(iterator, map); StoreObjectFieldRoot(iterator, JSRegExpStringIterator::kPropertiesOrHashOffset, @@ -2182,26 +2000,18 @@ TNode<Object> RegExpMatchAllAssembler::CreateRegExpStringIterator( StoreObjectFieldNoWriteBarrier( iterator, JSRegExpStringIterator::kIteratedStringOffset, string); -#ifdef DEBUG - // Verify global and full_unicode can be bitwise shifted without masking. - TNode<Int32T> zero = Int32Constant(0); - TNode<Int32T> one = Int32Constant(1); - CSA_ASSERT(this, - Word32Or(Word32Equal(global, zero), Word32Equal(global, one))); - CSA_ASSERT(this, Word32Or(Word32Equal(full_unicode, zero), - Word32Equal(full_unicode, one))); -#endif // DEBUG - // 7. Set iterator.[[Global]] to global. // 8. Set iterator.[[Unicode]] to fullUnicode. // 9. Set iterator.[[Done]] to false. - TNode<Word32T> global_flag = - Word32Shl(global, Int32Constant(JSRegExpStringIterator::kGlobalBit)); - TNode<Word32T> unicode_flag = Word32Shl( - full_unicode, Int32Constant(JSRegExpStringIterator::kUnicodeBit)); - TNode<Word32T> iterator_flags = Word32Or(global_flag, unicode_flag); + TNode<Int32T> global_flag = + Word32Shl(ReinterpretCast<Int32T>(global), + Int32Constant(JSRegExpStringIterator::kGlobalBit)); + TNode<Int32T> unicode_flag = + Word32Shl(ReinterpretCast<Int32T>(full_unicode), + Int32Constant(JSRegExpStringIterator::kUnicodeBit)); + TNode<Int32T> iterator_flags = Word32Or(global_flag, unicode_flag); StoreObjectFieldNoWriteBarrier(iterator, JSRegExpStringIterator::kFlagsOffset, - SmiFromInt32(Signed(iterator_flags))); + SmiFromInt32(iterator_flags)); return iterator; } @@ -2210,26 +2020,15 @@ TNode<Object> RegExpMatchAllAssembler::CreateRegExpStringIterator( // RegExp.prototype [ @@matchAll ] ( string ) TF_BUILTIN(RegExpPrototypeMatchAll, RegExpMatchAllAssembler) { TNode<Context> context = CAST(Parameter(Descriptor::kContext)); - TNode<Context> native_context = LoadNativeContext(context); + TNode<NativeContext> native_context = LoadNativeContext(context); TNode<Object> receiver = CAST(Parameter(Descriptor::kReceiver)); TNode<Object> maybe_string = CAST(Parameter(Descriptor::kString)); Generate(context, native_context, receiver, maybe_string); } -// Helper that skips a few initial checks. and assumes... -// 1) receiver is a "fast" RegExp -// 2) pattern is a string -TF_BUILTIN(RegExpMatchFast, RegExpBuiltinsAssembler) { - TNode<Object> receiver = CAST(Parameter(Descriptor::kReceiver)); - TNode<String> string = CAST(Parameter(Descriptor::kPattern)); - TNode<Context> context = CAST(Parameter(Descriptor::kContext)); - - RegExpPrototypeMatchBody(context, receiver, string, true); -} - void RegExpBuiltinsAssembler::RegExpPrototypeSearchBodyFast( TNode<Context> context, TNode<JSRegExp> regexp, TNode<String> string) { - CSA_ASSERT(this, IsFastRegExp(context, regexp)); + CSA_ASSERT(this, IsFastRegExpPermissive(context, regexp)); // Grab the initial value of last index. TNode<Smi> previous_last_index = FastLoadLastIndex(regexp); @@ -2248,7 +2047,7 @@ void RegExpBuiltinsAssembler::RegExpPrototypeSearchBodyFast( FastStoreLastIndex(regexp, previous_last_index); // Return the index of the match. - Node* const index = LoadFixedArrayElement( + TNode<Object> const index = LoadFixedArrayElement( match_indices, RegExpMatchInfo::kFirstCaptureIndex); Return(index); } @@ -2262,17 +2061,17 @@ void RegExpBuiltinsAssembler::RegExpPrototypeSearchBodyFast( } void RegExpBuiltinsAssembler::RegExpPrototypeSearchBodySlow( - Node* const context, Node* const regexp, Node* const string) { + TNode<Context> context, Node* const regexp, Node* const string) { CSA_ASSERT(this, IsJSReceiver(regexp)); CSA_ASSERT(this, IsString(string)); Isolate* const isolate = this->isolate(); - Node* const smi_zero = SmiZero(); + TNode<Smi> const smi_zero = SmiZero(); // Grab the initial value of last index. - Node* const previous_last_index = - SlowLoadLastIndex(CAST(context), CAST(regexp)); + TNode<Object> const previous_last_index = + SlowLoadLastIndex(context, CAST(regexp)); // Ensure last index is 0. { @@ -2286,13 +2085,13 @@ void RegExpBuiltinsAssembler::RegExpPrototypeSearchBodySlow( } // Call exec. - Node* const exec_result = RegExpExec(context, regexp, string); + TNode<Object> const exec_result = RegExpExec(context, regexp, string); // Reset last index if necessary. { Label next(this), slow(this, Label::kDeferred); - Node* const current_last_index = - SlowLoadLastIndex(CAST(context), CAST(regexp)); + TNode<Object> const current_last_index = + SlowLoadLastIndex(context, CAST(regexp)); BranchIfSameValue(current_last_index, previous_last_index, &next, &slow); @@ -2317,8 +2116,8 @@ void RegExpBuiltinsAssembler::RegExpPrototypeSearchBodySlow( BIND(&fast_result); { - Node* const index = - LoadObjectField(exec_result, JSRegExpResult::kIndexOffset); + TNode<Object> const index = + LoadObjectField(CAST(exec_result), JSRegExpResult::kIndexOffset); Return(index); } @@ -2341,13 +2140,13 @@ TF_BUILTIN(RegExpPrototypeSearch, RegExpBuiltinsAssembler) { ThrowIfNotJSReceiver(context, maybe_receiver, MessageTemplate::kIncompatibleMethodReceiver, "RegExp.prototype.@@search"); - Node* const receiver = maybe_receiver; + TNode<JSReceiver> receiver = CAST(maybe_receiver); // Convert {maybe_string} to a String. TNode<String> const string = ToString_Inline(context, maybe_string); Label fast_path(this), slow_path(this); - BranchIfFastRegExp(context, receiver, &fast_path, &slow_path); + BranchIfFastRegExp_Permissive(context, receiver, &fast_path, &slow_path); BIND(&fast_path); // TODO(pwong): Could be optimized to remove the overhead of calling the @@ -2371,13 +2170,12 @@ TF_BUILTIN(RegExpSearchFast, RegExpBuiltinsAssembler) { // Generates the fast path for @@split. {regexp} is an unmodified, non-sticky // JSRegExp, {string} is a String, and {limit} is a Smi. -void RegExpBuiltinsAssembler::RegExpPrototypeSplitBody(Node* const context, - Node* const regexp, +void RegExpBuiltinsAssembler::RegExpPrototypeSplitBody(TNode<Context> context, + TNode<JSRegExp> regexp, TNode<String> string, TNode<Smi> const limit) { - CSA_ASSERT(this, IsFastRegExp(context, regexp)); - CSA_ASSERT(this, - Word32BinaryNot(FastFlagGetter(CAST(regexp), JSRegExp::kSticky))); + CSA_ASSERT(this, IsFastRegExpPermissive(context, regexp)); + CSA_ASSERT(this, Word32BinaryNot(FastFlagGetter(regexp, JSRegExp::kSticky))); TNode<IntPtrT> const int_limit = SmiUntag(limit); @@ -2385,7 +2183,7 @@ void RegExpBuiltinsAssembler::RegExpPrototypeSplitBody(Node* const context, const ParameterMode mode = CodeStubAssembler::INTPTR_PARAMETERS; Node* const allocation_site = nullptr; - Node* const native_context = LoadNativeContext(context); + TNode<NativeContext> const native_context = LoadNativeContext(context); TNode<Map> array_map = LoadJSArrayElementsMap(kind, native_context); Label return_empty_array(this, Label::kDeferred); @@ -2407,10 +2205,10 @@ void RegExpBuiltinsAssembler::RegExpPrototypeSplitBody(Node* const context, BIND(&if_stringisempty); { - Node* const last_match_info = LoadContextElement( + TNode<Object> const last_match_info = LoadContextElement( native_context, Context::REGEXP_LAST_MATCH_INFO_INDEX); - Node* const match_indices = + TNode<Object> const match_indices = CallBuiltin(Builtins::kRegExpExecInternal, context, regexp, string, SmiZero(), last_match_info); @@ -2464,7 +2262,7 @@ void RegExpBuiltinsAssembler::RegExpPrototypeSplitBody(Node* const context, // Search for the given {regexp}. - Node* const last_match_info = LoadContextElement( + TNode<Object> const last_match_info = LoadContextElement( native_context, Context::REGEXP_LAST_MATCH_INFO_INDEX); TNode<HeapObject> const match_indices_ho = @@ -2499,8 +2297,9 @@ void RegExpBuiltinsAssembler::RegExpPrototypeSplitBody(Node* const context, GotoIfNot(SmiEqual(match_to, next_search_from), &next); GotoIfNot(SmiEqual(match_to, last_matched_until), &next); - Node* const is_unicode = FastFlagGetter(CAST(regexp), JSRegExp::kUnicode); - Node* const new_next_search_from = + TNode<BoolT> const is_unicode = + FastFlagGetter(regexp, JSRegExp::kUnicode); + TNode<Number> const new_next_search_from = AdvanceStringIndex(string, next_search_from, is_unicode, true); var_next_search_from = CAST(new_next_search_from); Goto(&loop); @@ -2518,9 +2317,9 @@ void RegExpBuiltinsAssembler::RegExpPrototypeSplitBody(Node* const context, // Add all captures to the array. { - Node* const num_registers = LoadFixedArrayElement( - match_indices, RegExpMatchInfo::kNumberOfCapturesIndex); - Node* const int_num_registers = SmiUntag(num_registers); + TNode<Smi> const num_registers = CAST(LoadFixedArrayElement( + match_indices, RegExpMatchInfo::kNumberOfCapturesIndex)); + TNode<IntPtrT> const int_num_registers = SmiUntag(num_registers); VARIABLE(var_reg, MachineType::PointerRepresentation()); var_reg.Bind(IntPtrConstant(2)); @@ -2535,7 +2334,7 @@ void RegExpBuiltinsAssembler::RegExpPrototypeSplitBody(Node* const context, BIND(&nested_loop); { Node* const reg = var_reg.value(); - Node* const from = LoadFixedArrayElement( + TNode<Object> const from = LoadFixedArrayElement( match_indices, reg, RegExpMatchInfo::kFirstCaptureIndex * kTaggedSize, mode); TNode<Smi> const to = CAST(LoadFixedArrayElement( @@ -2565,7 +2364,7 @@ void RegExpBuiltinsAssembler::RegExpPrototypeSplitBody(Node* const context, array.Push(CAST(var_value.value())); GotoIf(WordEqual(array.length(), int_limit), &out); - Node* const new_reg = IntPtrAdd(reg, IntPtrConstant(2)); + TNode<WordT> const new_reg = IntPtrAdd(reg, IntPtrConstant(2)); var_reg.Bind(new_reg); Branch(IntPtrLessThan(new_reg, int_num_registers), &nested_loop, @@ -2583,7 +2382,7 @@ void RegExpBuiltinsAssembler::RegExpPrototypeSplitBody(Node* const context, BIND(&push_suffix_and_out); { - Node* const from = var_last_matched_until.value(); + TNode<Smi> const from = var_last_matched_until.value(); Node* const to = string_length; array.Push(CallBuiltin(Builtins::kSubString, context, string, from, to)); Goto(&out); @@ -2591,7 +2390,7 @@ void RegExpBuiltinsAssembler::RegExpPrototypeSplitBody(Node* const context, BIND(&out); { - Node* const result = array.ToJSArray(CAST(context)); + TNode<JSArray> const result = array.ToJSArray(context); Return(result); } @@ -2612,11 +2411,9 @@ TF_BUILTIN(RegExpSplit, RegExpBuiltinsAssembler) { TNode<Object> maybe_limit = CAST(Parameter(Descriptor::kLimit)); TNode<Context> context = CAST(Parameter(Descriptor::kContext)); - CSA_ASSERT(this, IsFastRegExp(context, regexp)); - - // TODO(jgruber): Even if map checks send us to the fast path, we still need - // to verify the constructor property and jump to the slow path if it has - // been changed. + CSA_ASSERT_BRANCH(this, [&](Label* ok, Label* not_ok) { + BranchIfFastRegExp_Strict(context, regexp, ok, not_ok); + }); // Verify {maybe_limit}. @@ -2679,13 +2476,16 @@ TF_BUILTIN(RegExpPrototypeSplit, RegExpBuiltinsAssembler) { ThrowIfNotJSReceiver(context, maybe_receiver, MessageTemplate::kIncompatibleMethodReceiver, "RegExp.prototype.@@split"); - Node* const receiver = maybe_receiver; + TNode<JSReceiver> receiver = CAST(maybe_receiver); // Convert {maybe_string} to a String. - TNode<String> const string = ToString_Inline(context, maybe_string); + TNode<String> string = ToString_Inline(context, maybe_string); + // Strict: Reads the flags property. + // TODO(jgruber): Handle slow flag accesses on the fast path and make this + // permissive. Label stub(this), runtime(this, Label::kDeferred); - BranchIfFastRegExp(context, receiver, &stub, &runtime); + BranchIfFastRegExp_Strict(context, receiver, &stub, &runtime); BIND(&stub); args.PopAndReturn(CallBuiltin(Builtins::kRegExpSplit, context, receiver, @@ -2753,12 +2553,11 @@ TF_BUILTIN(RegExpStringIteratorPrototypeNext, RegExpStringIteratorAssembler) { GotoIf(HasDoneFlag(flags), &return_empty_done_result); // 5. Let R be O.[[IteratingRegExp]]. - TNode<Object> iterating_regexp = - LoadObjectField(receiver, JSRegExpStringIterator::kIteratingRegExpOffset); + TNode<JSReceiver> iterating_regexp = CAST(LoadObjectField( + receiver, JSRegExpStringIterator::kIteratingRegExpOffset)); - // TODO(jgruber): Verify that this is guaranteed. - CSA_CHECK(this, TaggedIsNotSmi(iterating_regexp)); - CSA_CHECK(this, IsJSReceiver(CAST(iterating_regexp))); + // For extra safety, also check the type in release mode. + CSA_CHECK(this, IsJSReceiver(iterating_regexp)); // 6. Let S be O.[[IteratedString]]. TNode<String> iterating_string = CAST( @@ -2775,23 +2574,23 @@ TF_BUILTIN(RegExpStringIteratorPrototypeNext, RegExpStringIteratorAssembler) { TVARIABLE(BoolT, var_is_fast_regexp); { Label if_fast(this), if_slow(this, Label::kDeferred); - BranchIfFastRegExp(context, iterating_regexp, &if_fast, &if_slow); + BranchIfFastRegExp_Permissive(context, iterating_regexp, &if_fast, + &if_slow); BIND(&if_fast); { TNode<RegExpMatchInfo> match_indices = - RegExpPrototypeExecBodyWithoutResult(context, CAST(iterating_regexp), - iterating_string, &if_no_match, - true); + RegExpPrototypeExecBodyWithoutResult( + context, iterating_regexp, iterating_string, &if_no_match, true); var_match = ConstructNewResultFromMatchInfo( - context, CAST(iterating_regexp), match_indices, iterating_string); + context, iterating_regexp, match_indices, iterating_string); var_is_fast_regexp = Int32TrueConstant(); Goto(&if_match); } BIND(&if_slow); { - var_match = CAST(RegExpExec(context, iterating_regexp, iterating_string)); + var_match = RegExpExec(context, iterating_regexp, iterating_string); var_is_fast_regexp = Int32FalseConstant(); Branch(IsNull(var_match.value()), &if_no_match, &if_match); } @@ -2836,7 +2635,7 @@ TF_BUILTIN(RegExpStringIteratorPrototypeNext, RegExpStringIteratorAssembler) { // When iterating_regexp is fast, we assume it stays fast even after // accessing the first match from the RegExp result. - CSA_ASSERT(this, IsFastRegExp(context, iterating_regexp)); + CSA_ASSERT(this, IsFastRegExpPermissive(context, iterating_regexp)); GotoIfNot(IsEmptyString(match_str), &return_result); // 1. Let thisIndex be ? ToLength(? Get(R, "lastIndex")). diff --git a/deps/v8/src/builtins/builtins-regexp-gen.h b/deps/v8/src/builtins/builtins-regexp-gen.h index 3677314f19..de841f57b2 100644 --- a/deps/v8/src/builtins/builtins-regexp-gen.h +++ b/deps/v8/src/builtins/builtins-regexp-gen.h @@ -17,11 +17,6 @@ class RegExpBuiltinsAssembler : public CodeStubAssembler { explicit RegExpBuiltinsAssembler(compiler::CodeAssemblerState* state) : CodeStubAssembler(state) {} - void BranchIfFastRegExp( - Node* const context, Node* const object, Node* const map, - base::Optional<DescriptorIndexAndName> additional_property_to_check, - Label* const if_isunmodified, Label* const if_ismodified); - // Create and initialize a RegExp object. TNode<Object> RegExpCreate(TNode<Context> context, TNode<Context> native_context, @@ -35,6 +30,8 @@ class RegExpBuiltinsAssembler : public CodeStubAssembler { TNode<Smi> SmiZero(); TNode<IntPtrT> IntPtrZero(); + TNode<RawPtrT> LoadCodeObjectEntry(TNode<Code> code); + // Allocate a RegExpResult with the given length (the number of captures, // including the match itself), index (the index where the match starts), // and input string. @@ -53,7 +50,7 @@ class RegExpBuiltinsAssembler : public CodeStubAssembler { void FastStoreLastIndex(TNode<JSRegExp> regexp, TNode<Smi> value); void SlowStoreLastIndex(SloppyTNode<Context> context, SloppyTNode<Object> regexp, - SloppyTNode<Number> value); + SloppyTNode<Object> value); void StoreLastIndex(TNode<Context> context, TNode<Object> regexp, TNode<Number> value, bool is_fastpath); @@ -79,7 +76,7 @@ class RegExpBuiltinsAssembler : public CodeStubAssembler { 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<Context> context, TNode<JSRegExp> maybe_regexp, TNode<String> string, Label* if_didnotmatch); TNode<HeapObject> RegExpPrototypeExecBody(TNode<Context> context, @@ -87,50 +84,90 @@ class RegExpBuiltinsAssembler : public CodeStubAssembler { TNode<String> string, const bool is_fastpath); - Node* ThrowIfNotJSReceiver(Node* context, Node* maybe_receiver, - MessageTemplate msg_template, - char const* method_name); - - // Analogous to BranchIfFastRegExp, for use in asserts. - TNode<BoolT> IsFastRegExp(SloppyTNode<Context> context, - SloppyTNode<Object> object); + TNode<BoolT> IsReceiverInitialRegExpPrototype(SloppyTNode<Context> context, + SloppyTNode<Object> receiver); + + // Fast path check logic. + // + // Are you afraid? If not, you should be. + // + // It's complicated. Fast path checks protect certain assumptions, e.g. that + // relevant properties on the regexp prototype (such as exec, @@split, global) + // are unmodified. + // + // These assumptions differ by callsite. For example, RegExpPrototypeExec + // cares whether the exec property has been modified; but it's totally fine + // to modify other prototype properties. On the other hand, + // StringPrototypeSplit does care very much whether @@split has been changed. + // + // We want to keep regexp execution on the fast path as much as possible. + // Ideally, we could simply check if the regexp prototype has been modified; + // yet common web frameworks routinely mutate it for various reasons. But most + // of these mutations should happen in a way that still allows us to remain + // on the fast path. To support this, the fast path check logic necessarily + // becomes more involved. + // + // There are multiple knobs to twiddle for regexp fast path checks. We support + // checks that completely ignore the prototype, checks that verify specific + // properties on the prototype (the caller must ensure it passes in the right + // ones), and strict checks that additionally ensure the prototype is + // unchanged (we use these when we'd have to check multiple properties we + // don't care too much about, e.g. all individual flag getters). + + using DescriptorIndexNameValue = + PrototypeCheckAssembler::DescriptorIndexNameValue; - void BranchIfFastRegExp(Node* const context, Node* const object, - Label* const if_isunmodified, - Label* const if_ismodified); + void BranchIfFastRegExp( + TNode<Context> context, TNode<HeapObject> object, TNode<Map> map, + PrototypeCheckAssembler::Flags prototype_check_flags, + base::Optional<DescriptorIndexNameValue> additional_property_to_check, + Label* if_isunmodified, Label* if_ismodified); + + // Strict: Does not tolerate any changes to the prototype map. + // Permissive: Allows changes to the prototype map except for the exec + // property. + void BranchIfFastRegExp_Strict(TNode<Context> context, + TNode<HeapObject> object, + Label* if_isunmodified, Label* if_ismodified); + void BranchIfFastRegExp_Permissive(TNode<Context> context, + TNode<HeapObject> object, + Label* if_isunmodified, + Label* if_ismodified); // Performs fast path checks on the given object itself, but omits prototype // checks. - Node* IsFastRegExpNoPrototype(Node* const context, Node* const object); + Node* IsFastRegExpNoPrototype(SloppyTNode<Context> context, + SloppyTNode<Object> object); + Node* IsFastRegExpNoPrototype(SloppyTNode<Context> context, + SloppyTNode<Object> object, + SloppyTNode<Map> map); + + // For debugging only. Uses a slow GetProperty call to fetch object.exec. TNode<BoolT> IsFastRegExpWithOriginalExec(TNode<Context> context, TNode<JSRegExp> object); - Node* IsFastRegExpNoPrototype(Node* const context, Node* const object, - Node* const map); void BranchIfFastRegExpResult(Node* const context, Node* const object, Label* if_isunmodified, Label* if_ismodified); - Node* FlagsGetter(Node* const context, Node* const regexp, bool is_fastpath); + TNode<String> FlagsGetter(TNode<Context> context, TNode<Object> regexp, + const bool is_fastpath); - TNode<Int32T> FastFlagGetter(TNode<JSRegExp> regexp, JSRegExp::Flag flag); + TNode<BoolT> FastFlagGetter(TNode<JSRegExp> regexp, JSRegExp::Flag flag); TNode<BoolT> FastFlagGetterGlobal(TNode<JSRegExp> regexp) { - return ReinterpretCast<BoolT>(FastFlagGetter(regexp, JSRegExp::kGlobal)); + return FastFlagGetter(regexp, JSRegExp::kGlobal); } TNode<BoolT> FastFlagGetterUnicode(TNode<JSRegExp> regexp) { - return ReinterpretCast<BoolT>(FastFlagGetter(regexp, JSRegExp::kUnicode)); + return 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, - JSRegExp::Flag flag, bool is_fastpath); - - void FlagGetter(Node* context, Node* receiver, JSRegExp::Flag flag, - int counter, const char* method_name); + TNode<BoolT> SlowFlagGetter(TNode<Context> context, TNode<Object> regexp, + JSRegExp::Flag flag); + TNode<BoolT> FlagGetter(TNode<Context> context, TNode<Object> regexp, + JSRegExp::Flag flag, bool is_fastpath); Node* RegExpInitialize(Node* const context, Node* const regexp, Node* const maybe_pattern, Node* const maybe_flags); - Node* RegExpExec(Node* context, Node* regexp, Node* string); + TNode<Object> RegExpExec(TNode<Context> context, Node* regexp, Node* string); TNode<Number> AdvanceStringIndex(SloppyTNode<String> string, SloppyTNode<Number> index, @@ -142,17 +179,18 @@ class RegExpBuiltinsAssembler : public CodeStubAssembler { return CAST(AdvanceStringIndex(string, index, is_unicode, true)); } - void RegExpPrototypeMatchBody(TNode<Context> context, TNode<Object> regexp, - TNode<String> const string, - const bool is_fastpath); + TNode<Object> RegExpPrototypeMatchBody(TNode<Context> context, + TNode<Object> regexp, + TNode<String> const string, + const bool is_fastpath); void RegExpPrototypeSearchBodyFast(TNode<Context> context, TNode<JSRegExp> regexp, TNode<String> string); - void RegExpPrototypeSearchBodySlow(Node* const context, Node* const regexp, + void RegExpPrototypeSearchBodySlow(TNode<Context> context, Node* const regexp, Node* const string); - void RegExpPrototypeSplitBody(Node* const context, Node* const regexp, + void RegExpPrototypeSplitBody(TNode<Context> context, TNode<JSRegExp> regexp, TNode<String> const string, TNode<Smi> const limit); }; @@ -165,8 +203,8 @@ class RegExpMatchAllAssembler : public RegExpBuiltinsAssembler { TNode<Object> CreateRegExpStringIterator(TNode<Context> native_context, TNode<Object> regexp, TNode<String> string, - TNode<Int32T> global, - TNode<Int32T> full_unicode); + TNode<BoolT> global, + TNode<BoolT> full_unicode); void Generate(TNode<Context> context, TNode<Context> native_context, TNode<Object> receiver, TNode<Object> maybe_string); }; diff --git a/deps/v8/src/builtins/builtins-sharedarraybuffer-gen.cc b/deps/v8/src/builtins/builtins-sharedarraybuffer-gen.cc index 1e9ac8377c..8ae89187ec 100644 --- a/deps/v8/src/builtins/builtins-sharedarraybuffer-gen.cc +++ b/deps/v8/src/builtins/builtins-sharedarraybuffer-gen.cc @@ -26,7 +26,7 @@ class SharedArrayBufferBuiltinsAssembler : public CodeStubAssembler { Node* value, Node* value_high); void ValidateSharedTypedArray(Node* tagged, Node* context, - Node** out_elements_kind, + TNode<Int32T>* out_elements_kind, Node** out_backing_store); Node* ConvertTaggedAtomicIndexToWord32(Node* tagged, Node* context, Node** number_index); @@ -46,7 +46,7 @@ class SharedArrayBufferBuiltinsAssembler : public CodeStubAssembler { }; void SharedArrayBufferBuiltinsAssembler::ValidateSharedTypedArray( - Node* tagged, Node* context, Node** out_elements_kind, + Node* tagged, Node* context, TNode<Int32T>* out_elements_kind, Node** out_backing_store) { Label not_float_or_clamped(this), invalid(this); @@ -54,7 +54,7 @@ void SharedArrayBufferBuiltinsAssembler::ValidateSharedTypedArray( GotoIf(TaggedIsSmi(tagged), &invalid); // Fail if the array's instance type is not JSTypedArray. - Node* tagged_map = LoadMap(tagged); + TNode<Map> tagged_map = LoadMap(tagged); GotoIfNot(IsJSTypedArrayMap(tagged_map), &invalid); // Fail if the array's JSArrayBuffer is not shared. @@ -69,7 +69,7 @@ void SharedArrayBufferBuiltinsAssembler::ValidateSharedTypedArray( STATIC_ASSERT(UINT8_ELEMENTS < FLOAT32_ELEMENTS); STATIC_ASSERT(UINT16_ELEMENTS < FLOAT32_ELEMENTS); STATIC_ASSERT(UINT32_ELEMENTS < FLOAT32_ELEMENTS); - Node* elements_kind = LoadMapElementsKind(tagged_map); + TNode<Int32T> elements_kind = LoadMapElementsKind(tagged_map); GotoIf(Int32LessThan(elements_kind, Int32Constant(FLOAT32_ELEMENTS)), ¬_float_or_clamped); STATIC_ASSERT(BIGINT64_ELEMENTS > UINT8_CLAMPED_ELEMENTS); @@ -167,7 +167,7 @@ TF_BUILTIN(AtomicsLoad, SharedArrayBufferBuiltinsAssembler) { Node* index = Parameter(Descriptor::kIndex); Node* context = Parameter(Descriptor::kContext); - Node* elements_kind; + TNode<Int32T> elements_kind; Node* backing_store; ValidateSharedTypedArray(array, context, &elements_kind, &backing_store); @@ -175,7 +175,7 @@ TF_BUILTIN(AtomicsLoad, SharedArrayBufferBuiltinsAssembler) { Node* index_word32 = ConvertTaggedAtomicIndexToWord32(index, context, &index_integer); ValidateAtomicIndex(array, index_word32, context); - Node* index_word = ChangeUint32ToWord(index_word32); + TNode<UintPtrT> index_word = ChangeUint32ToWord(index_word32); Label i8(this), u8(this), i16(this), u16(this), i32(this), u32(this), i64(this), u64(this), other(this); @@ -239,7 +239,7 @@ TF_BUILTIN(AtomicsStore, SharedArrayBufferBuiltinsAssembler) { Node* value = Parameter(Descriptor::kValue); Node* context = Parameter(Descriptor::kContext); - Node* elements_kind; + TNode<Int32T> elements_kind; Node* backing_store; ValidateSharedTypedArray(array, context, &elements_kind, &backing_store); @@ -247,14 +247,14 @@ TF_BUILTIN(AtomicsStore, SharedArrayBufferBuiltinsAssembler) { Node* index_word32 = ConvertTaggedAtomicIndexToWord32(index, context, &index_integer); ValidateAtomicIndex(array, index_word32, context); - Node* index_word = ChangeUint32ToWord(index_word32); + TNode<UintPtrT> index_word = ChangeUint32ToWord(index_word32); Label u8(this), u16(this), u32(this), u64(this), other(this); STATIC_ASSERT(BIGINT64_ELEMENTS > INT32_ELEMENTS); STATIC_ASSERT(BIGUINT64_ELEMENTS > INT32_ELEMENTS); GotoIf(Int32GreaterThan(elements_kind, Int32Constant(INT32_ELEMENTS)), &u64); - Node* value_integer = ToInteger_Inline(CAST(context), CAST(value)); + TNode<Number> value_integer = ToInteger_Inline(CAST(context), CAST(value)); Node* value_word32 = TruncateTaggedToWord32(context, value_integer); #if DEBUG @@ -313,7 +313,7 @@ TF_BUILTIN(AtomicsExchange, SharedArrayBufferBuiltinsAssembler) { Node* value = Parameter(Descriptor::kValue); Node* context = Parameter(Descriptor::kContext); - Node* elements_kind; + TNode<Int32T> elements_kind; Node* backing_store; ValidateSharedTypedArray(array, context, &elements_kind, &backing_store); @@ -326,7 +326,7 @@ TF_BUILTIN(AtomicsExchange, SharedArrayBufferBuiltinsAssembler) { Return(CallRuntime(Runtime::kAtomicsExchange, context, array, index_integer, value)); #else - Node* index_word = ChangeUint32ToWord(index_word32); + TNode<UintPtrT> index_word = ChangeUint32ToWord(index_word32); Label i8(this), u8(this), i16(this), u16(this), i32(this), u32(this), i64(this), u64(this), big(this), other(this); @@ -334,7 +334,7 @@ TF_BUILTIN(AtomicsExchange, SharedArrayBufferBuiltinsAssembler) { STATIC_ASSERT(BIGUINT64_ELEMENTS > INT32_ELEMENTS); GotoIf(Int32GreaterThan(elements_kind, Int32Constant(INT32_ELEMENTS)), &big); - Node* value_integer = ToInteger_Inline(CAST(context), CAST(value)); + TNode<Number> value_integer = ToInteger_Inline(CAST(context), CAST(value)); #if DEBUG DebugSanityCheckAtomicIndex(array, index_word32, context); #endif @@ -415,7 +415,7 @@ TF_BUILTIN(AtomicsCompareExchange, SharedArrayBufferBuiltinsAssembler) { Node* new_value = Parameter(Descriptor::kNewValue); Node* context = Parameter(Descriptor::kContext); - Node* elements_kind; + TNode<Int32T> elements_kind; Node* backing_store; ValidateSharedTypedArray(array, context, &elements_kind, &backing_store); @@ -429,7 +429,7 @@ TF_BUILTIN(AtomicsCompareExchange, SharedArrayBufferBuiltinsAssembler) { Return(CallRuntime(Runtime::kAtomicsCompareExchange, context, array, index_integer, old_value, new_value)); #else - Node* index_word = ChangeUint32ToWord(index_word32); + TNode<UintPtrT> index_word = ChangeUint32ToWord(index_word32); Label i8(this), u8(this), i16(this), u16(this), i32(this), u32(this), i64(this), u64(this), big(this), other(this); @@ -437,8 +437,10 @@ TF_BUILTIN(AtomicsCompareExchange, SharedArrayBufferBuiltinsAssembler) { STATIC_ASSERT(BIGUINT64_ELEMENTS > INT32_ELEMENTS); GotoIf(Int32GreaterThan(elements_kind, Int32Constant(INT32_ELEMENTS)), &big); - Node* old_value_integer = ToInteger_Inline(CAST(context), CAST(old_value)); - Node* new_value_integer = ToInteger_Inline(CAST(context), CAST(new_value)); + TNode<Number> old_value_integer = + ToInteger_Inline(CAST(context), CAST(old_value)); + TNode<Number> new_value_integer = + ToInteger_Inline(CAST(context), CAST(new_value)); #if DEBUG DebugSanityCheckAtomicIndex(array, index_word32, context); #endif @@ -543,7 +545,7 @@ BINOP_BUILTIN(Xor) void SharedArrayBufferBuiltinsAssembler::AtomicBinopBuiltinCommon( Node* array, Node* index, Node* value, Node* context, AssemblerFunction function, Runtime::FunctionId runtime_function) { - Node* elements_kind; + TNode<Int32T> elements_kind; Node* backing_store; ValidateSharedTypedArray(array, context, &elements_kind, &backing_store); @@ -556,7 +558,7 @@ void SharedArrayBufferBuiltinsAssembler::AtomicBinopBuiltinCommon( V8_TARGET_ARCH_PPC || V8_TARGET_ARCH_S390 || V8_TARGET_ARCH_S390X Return(CallRuntime(runtime_function, context, array, index_integer, value)); #else - Node* index_word = ChangeUint32ToWord(index_word32); + TNode<UintPtrT> index_word = ChangeUint32ToWord(index_word32); Label i8(this), u8(this), i16(this), u16(this), i32(this), u32(this), i64(this), u64(this), big(this), other(this); @@ -565,7 +567,7 @@ void SharedArrayBufferBuiltinsAssembler::AtomicBinopBuiltinCommon( STATIC_ASSERT(BIGUINT64_ELEMENTS > INT32_ELEMENTS); GotoIf(Int32GreaterThan(elements_kind, Int32Constant(INT32_ELEMENTS)), &big); - Node* value_integer = ToInteger_Inline(CAST(context), CAST(value)); + TNode<Number> value_integer = ToInteger_Inline(CAST(context), CAST(value)); #if DEBUG DebugSanityCheckAtomicIndex(array, index_word32, context); #endif diff --git a/deps/v8/src/builtins/builtins-sharedarraybuffer.cc b/deps/v8/src/builtins/builtins-sharedarraybuffer.cc index fa6534d463..e6251c9480 100644 --- a/deps/v8/src/builtins/builtins-sharedarraybuffer.cc +++ b/deps/v8/src/builtins/builtins-sharedarraybuffer.cc @@ -22,8 +22,23 @@ namespace internal { // See builtins-arraybuffer.cc for implementations of // SharedArrayBuffer.prototye.byteLength and SharedArrayBuffer.prototype.slice +// #sec-atomics.islockfree inline bool AtomicIsLockFree(double size) { - return size == 1 || size == 2 || size == 4; + // According to the standard, 1, 2, and 4 byte atomics are supposed to be + // 'lock free' on every platform. But what exactly does 'lock free' mean? + // For example, on x64 V8 uses a lock prefix to implement the semantics of + // many atomic operations. Is that considered a lock? Probably not. + // + // On the other hand, V8 emits a few instructions for some arm atomics which + // do appear to be a low level form of a spin lock. With an abundance of + // caution, we only claim to have 'true lock free' support for 8 byte sizes + // on x64 platforms. If people care about this function returning true, then + // we need to clarify exactly what 'lock free' means at the standard level. + bool is_lock_free = size == 1 || size == 2 || size == 4; +#if V8_TARGET_ARCH_x64 + is_lock_free |= size == 8; +#endif + return is_lock_free; } // ES #sec-atomics.islockfree @@ -37,12 +52,16 @@ BUILTIN(AtomicsIsLockFree) { // ES #sec-validatesharedintegertypedarray V8_WARN_UNUSED_RESULT MaybeHandle<JSTypedArray> ValidateSharedIntegerTypedArray( - Isolate* isolate, Handle<Object> object, bool only_int32 = false) { + Isolate* isolate, Handle<Object> object, + bool only_int32_and_big_int64 = false) { if (object->IsJSTypedArray()) { Handle<JSTypedArray> typed_array = Handle<JSTypedArray>::cast(object); if (typed_array->GetBuffer()->is_shared()) { - if (only_int32) { - if (typed_array->type() == kExternalInt32Array) return typed_array; + if (only_int32_and_big_int64) { + if (typed_array->type() == kExternalInt32Array || + typed_array->type() == kExternalBigInt64Array) { + return typed_array; + } } else { if (typed_array->type() != kExternalFloat32Array && typed_array->type() != kExternalFloat64Array && @@ -54,8 +73,9 @@ V8_WARN_UNUSED_RESULT MaybeHandle<JSTypedArray> ValidateSharedIntegerTypedArray( THROW_NEW_ERROR( isolate, - NewTypeError(only_int32 ? MessageTemplate::kNotInt32SharedTypedArray - : MessageTemplate::kNotIntegerSharedTypedArray, + NewTypeError(only_int32_and_big_int64 + ? MessageTemplate::kNotInt32OrBigInt64SharedTypedArray + : MessageTemplate::kNotIntegerSharedTypedArray, object), JSTypedArray); } @@ -83,6 +103,15 @@ V8_WARN_UNUSED_RESULT Maybe<size_t> ValidateAtomicAccess( } namespace { + +inline size_t GetAddress64(size_t index, size_t byte_offset) { + return (index << 3) + byte_offset; +} + +inline size_t GetAddress32(size_t index, size_t byte_offset) { + return (index << 2) + byte_offset; +} + MaybeHandle<Object> AtomicsWake(Isolate* isolate, Handle<Object> array, Handle<Object> index, Handle<Object> count) { Handle<JSTypedArray> sta; @@ -109,9 +138,19 @@ MaybeHandle<Object> AtomicsWake(Isolate* isolate, Handle<Object> array, } Handle<JSArrayBuffer> array_buffer = sta->GetBuffer(); - size_t addr = (i << 2) + sta->byte_offset(); - return Handle<Object>(FutexEmulation::Wake(array_buffer, addr, c), isolate); + if (sta->type() == kExternalBigInt64Array) { + return Handle<Object>( + FutexEmulation::Wake(array_buffer, GetAddress64(i, sta->byte_offset()), + c), + isolate); + } else { + DCHECK(sta->type() == kExternalInt32Array); + return Handle<Object>( + FutexEmulation::Wake(array_buffer, GetAddress32(i, sta->byte_offset()), + c), + isolate); + } } } // namespace @@ -157,9 +196,16 @@ BUILTIN(AtomicsWait) { if (maybe_index.IsNothing()) return ReadOnlyRoots(isolate).exception(); size_t i = maybe_index.FromJust(); - ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, value, - Object::ToInt32(isolate, value)); - int32_t value_int32 = NumberToInt32(*value); + // According to the spec, we have to check value's type before + // looking at the timeout. + if (sta->type() == kExternalBigInt64Array) { + ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, value, + BigInt::FromObject(isolate, value)); + } else { + DCHECK(sta->type() == kExternalInt32Array); + ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, value, + Object::ToInt32(isolate, value)); + } double timeout_number; if (timeout->IsUndefined(isolate)) { @@ -180,10 +226,17 @@ BUILTIN(AtomicsWait) { } Handle<JSArrayBuffer> array_buffer = sta->GetBuffer(); - size_t addr = (i << 2) + sta->byte_offset(); - return FutexEmulation::WaitJs(isolate, array_buffer, addr, value_int32, - timeout_number); + if (sta->type() == kExternalBigInt64Array) { + return FutexEmulation::WaitJs64( + isolate, array_buffer, GetAddress64(i, sta->byte_offset()), + Handle<BigInt>::cast(value)->AsInt64(), timeout_number); + } else { + DCHECK(sta->type() == kExternalInt32Array); + return FutexEmulation::WaitJs32(isolate, array_buffer, + GetAddress32(i, sta->byte_offset()), + NumberToInt32(*value), timeout_number); + } } } // namespace internal diff --git a/deps/v8/src/builtins/builtins-string-gen.cc b/deps/v8/src/builtins/builtins-string-gen.cc index 97dc8ca895..fc2745ed0a 100644 --- a/deps/v8/src/builtins/builtins-string-gen.cc +++ b/deps/v8/src/builtins/builtins-string-gen.cc @@ -65,11 +65,13 @@ void StringBuiltinsAssembler::DispatchOnStringEncodings( // First combine the encodings. - Node* const encoding_mask = Int32Constant(kStringEncodingMask); - Node* const lhs_encoding = Word32And(lhs_instance_type, encoding_mask); - Node* const rhs_encoding = Word32And(rhs_instance_type, encoding_mask); + TNode<Int32T> const encoding_mask = Int32Constant(kStringEncodingMask); + TNode<Word32T> const lhs_encoding = + Word32And(lhs_instance_type, encoding_mask); + TNode<Word32T> const rhs_encoding = + Word32And(rhs_instance_type, encoding_mask); - Node* const combined_encodings = + TNode<Word32T> const combined_encodings = Word32Or(lhs_encoding, Word32Shr(rhs_encoding, 1)); // Then dispatch on the combined encoding. @@ -99,9 +101,9 @@ Node* StringBuiltinsAssembler::CallSearchStringRaw(Node* const subject_ptr, Node* const search_ptr, Node* const search_length, Node* const start_position) { - Node* const function_addr = ExternalConstant( + TNode<ExternalReference> const function_addr = ExternalConstant( ExternalReference::search_string_raw<SubjectChar, PatternChar>()); - Node* const isolate_ptr = + TNode<ExternalReference> const isolate_ptr = ExternalConstant(ExternalReference::isolate_address(isolate())); MachineType type_ptr = MachineType::Pointer(); @@ -118,20 +120,20 @@ Node* StringBuiltinsAssembler::CallSearchStringRaw(Node* const subject_ptr, return result; } -Node* StringBuiltinsAssembler::PointerToStringDataAtIndex( +TNode<IntPtrT> StringBuiltinsAssembler::PointerToStringDataAtIndex( Node* const string_data, Node* const index, String::Encoding encoding) { const ElementsKind kind = (encoding == String::ONE_BYTE_ENCODING) ? UINT8_ELEMENTS : UINT16_ELEMENTS; - Node* const offset_in_bytes = + TNode<IntPtrT> const offset_in_bytes = ElementOffsetFromIndex(index, kind, INTPTR_PARAMETERS); - return IntPtrAdd(string_data, offset_in_bytes); + return Signed(IntPtrAdd(string_data, offset_in_bytes)); } -void StringBuiltinsAssembler::GenerateStringEqual(Node* context, Node* left, - Node* right) { - VARIABLE(var_left, MachineRepresentation::kTagged, left); - VARIABLE(var_right, MachineRepresentation::kTagged, right); +void StringBuiltinsAssembler::GenerateStringEqual(TNode<String> left, + TNode<String> right) { + TVARIABLE(String, var_left, left); + TVARIABLE(String, var_right, right); Label if_equal(this), if_notequal(this), if_indirect(this, Label::kDeferred), restart(this, {&var_left, &var_right}); @@ -143,14 +145,14 @@ void StringBuiltinsAssembler::GenerateStringEqual(Node* context, Node* left, Goto(&restart); BIND(&restart); - Node* lhs = var_left.value(); - Node* rhs = var_right.value(); + TNode<String> lhs = var_left.value(); + TNode<String> rhs = var_right.value(); - Node* lhs_instance_type = LoadInstanceType(lhs); - Node* rhs_instance_type = LoadInstanceType(rhs); + TNode<Uint16T> lhs_instance_type = LoadInstanceType(lhs); + TNode<Uint16T> rhs_instance_type = LoadInstanceType(rhs); - StringEqual_Core(context, lhs, lhs_instance_type, rhs, rhs_instance_type, - lhs_length, &if_equal, &if_notequal, &if_indirect); + StringEqual_Core(lhs, lhs_instance_type, rhs, rhs_instance_type, lhs_length, + &if_equal, &if_notequal, &if_indirect); BIND(&if_indirect); { @@ -158,7 +160,7 @@ void StringBuiltinsAssembler::GenerateStringEqual(Node* context, Node* left, MaybeDerefIndirectStrings(&var_left, lhs_instance_type, &var_right, rhs_instance_type, &restart); - TailCallRuntime(Runtime::kStringEqual, context, lhs, rhs); + TailCallRuntime(Runtime::kStringEqual, NoContextConstant(), lhs, rhs); } BIND(&if_equal); @@ -169,19 +171,17 @@ void StringBuiltinsAssembler::GenerateStringEqual(Node* context, Node* left, } void StringBuiltinsAssembler::StringEqual_Core( - Node* context, Node* lhs, Node* lhs_instance_type, Node* rhs, + SloppyTNode<String> lhs, Node* lhs_instance_type, SloppyTNode<String> rhs, Node* rhs_instance_type, TNode<IntPtrT> length, Label* if_equal, Label* if_not_equal, Label* if_indirect) { - CSA_ASSERT(this, IsString(lhs)); - CSA_ASSERT(this, IsString(rhs)); CSA_ASSERT(this, WordEqual(LoadStringLengthAsWord(lhs), length)); CSA_ASSERT(this, WordEqual(LoadStringLengthAsWord(rhs), length)); // Fast check to see if {lhs} and {rhs} refer to the same String object. - GotoIf(WordEqual(lhs, rhs), if_equal); + GotoIf(TaggedEqual(lhs, rhs), if_equal); // Combine the instance types into a single 16-bit value, so we can check // both of them at once. - Node* both_instance_types = Word32Or( + TNode<Word32T> both_instance_types = Word32Or( lhs_instance_type, Word32Shl(rhs_instance_type, Int32Constant(8))); // Check if both {lhs} and {rhs} are internalized. Since we already know @@ -214,7 +214,7 @@ void StringBuiltinsAssembler::StringEqual_Core( int const kOneTwoByteStringTag = kOneByteStringTag | (kTwoByteStringTag << 8); Label if_oneonebytestring(this), if_twotwobytestring(this), if_onetwobytestring(this), if_twoonebytestring(this); - Node* masked_instance_types = + TNode<Word32T> masked_instance_types = Word32And(both_instance_types, Int32Constant(kBothStringEncodingMask)); GotoIf( Word32Equal(masked_instance_types, Int32Constant(kOneOneByteStringTag)), @@ -271,14 +271,14 @@ void StringBuiltinsAssembler::StringEqual_Loop( GotoIf(WordEqual(var_offset.value(), length), if_equal); // Load the next characters from {lhs} and {rhs}. - Node* lhs_value = + TNode<Word32T> lhs_value = UncheckedCast<Word32T>( Load(lhs_type, lhs_data, WordShl(var_offset.value(), - ElementSizeLog2Of(lhs_type.representation()))); - Node* rhs_value = + ElementSizeLog2Of(lhs_type.representation())))); + TNode<Word32T> rhs_value = UncheckedCast<Word32T>( Load(rhs_type, rhs_data, WordShl(var_offset.value(), - ElementSizeLog2Of(rhs_type.representation()))); + ElementSizeLog2Of(rhs_type.representation())))); // Check if the characters match. GotoIf(Word32NotEqual(lhs_value, rhs_value), if_not_equal); @@ -296,28 +296,6 @@ TF_BUILTIN(StringAdd_CheckNone, StringBuiltinsAssembler) { Return(StringAdd(context, left, right)); } -TF_BUILTIN(StringAdd_ConvertLeft, StringBuiltinsAssembler) { - TNode<Object> left = CAST(Parameter(Descriptor::kLeft)); - TNode<String> right = CAST(Parameter(Descriptor::kRight)); - Node* context = Parameter(Descriptor::kContext); - // TODO(danno): The ToString and JSReceiverToPrimitive below could be - // combined to avoid duplicate smi and instance type checks. - left = - ToStringImpl(CAST(context), CAST(JSReceiverToPrimitive(context, left))); - TailCallBuiltin(Builtins::kStringAdd_CheckNone, context, left, right); -} - -TF_BUILTIN(StringAdd_ConvertRight, StringBuiltinsAssembler) { - TNode<String> left = CAST(Parameter(Descriptor::kLeft)); - TNode<Object> right = CAST(Parameter(Descriptor::kRight)); - Node* context = Parameter(Descriptor::kContext); - // TODO(danno): The ToString and JSReceiverToPrimitive below could be - // combined to avoid duplicate smi and instance type checks. - right = - ToStringImpl(CAST(context), CAST(JSReceiverToPrimitive(context, right))); - TailCallBuiltin(Builtins::kStringAdd_CheckNone, context, left, right); -} - TF_BUILTIN(SubString, StringBuiltinsAssembler) { TNode<String> string = CAST(Parameter(Descriptor::kString)); TNode<Smi> from = CAST(Parameter(Descriptor::kFrom)); @@ -325,12 +303,10 @@ TF_BUILTIN(SubString, StringBuiltinsAssembler) { Return(SubString(string, SmiUntag(from), SmiUntag(to))); } -void StringBuiltinsAssembler::GenerateStringRelationalComparison(Node* context, - Node* left, - Node* right, - Operation op) { - VARIABLE(var_left, MachineRepresentation::kTagged, left); - VARIABLE(var_right, MachineRepresentation::kTagged, right); +void StringBuiltinsAssembler::GenerateStringRelationalComparison( + TNode<String> left, TNode<String> right, Operation op) { + TVARIABLE(String, var_left, left); + TVARIABLE(String, var_right, right); Variable* input_vars[2] = {&var_left, &var_right}; Label if_less(this), if_equal(this), if_greater(this); @@ -338,18 +314,18 @@ void StringBuiltinsAssembler::GenerateStringRelationalComparison(Node* context, Goto(&restart); BIND(&restart); - Node* lhs = var_left.value(); - Node* rhs = var_right.value(); + TNode<String> lhs = var_left.value(); + TNode<String> rhs = var_right.value(); // Fast check to see if {lhs} and {rhs} refer to the same String object. - GotoIf(WordEqual(lhs, rhs), &if_equal); + GotoIf(TaggedEqual(lhs, rhs), &if_equal); // Load instance types of {lhs} and {rhs}. - Node* lhs_instance_type = LoadInstanceType(lhs); - Node* rhs_instance_type = LoadInstanceType(rhs); + TNode<Uint16T> lhs_instance_type = LoadInstanceType(lhs); + TNode<Uint16T> rhs_instance_type = LoadInstanceType(rhs); // Combine the instance types into a single 16-bit value, so we can check // both of them at once. - Node* both_instance_types = Word32Or( + TNode<Int32T> both_instance_types = Word32Or( lhs_instance_type, Word32Shl(rhs_instance_type, Int32Constant(8))); // Check that both {lhs} and {rhs} are flat one-byte strings. @@ -394,8 +370,8 @@ void StringBuiltinsAssembler::GenerateStringRelationalComparison(Node* context, BIND(&if_notdone); { // Load the next characters from {lhs} and {rhs}. - Node* lhs_value = Load(MachineType::Uint8(), lhs, var_offset.value()); - Node* rhs_value = Load(MachineType::Uint8(), rhs, var_offset.value()); + TNode<Uint8T> lhs_value = Load<Uint8T>(lhs, var_offset.value()); + TNode<Uint8T> rhs_value = Load<Uint8T>(rhs, var_offset.value()); // Check if the characters match. Label if_valueissame(this), if_valueisnotsame(this); @@ -431,16 +407,20 @@ void StringBuiltinsAssembler::GenerateStringRelationalComparison(Node* context, // TODO(bmeurer): Add support for two byte string relational comparisons. switch (op) { case Operation::kLessThan: - TailCallRuntime(Runtime::kStringLessThan, context, lhs, rhs); + TailCallRuntime(Runtime::kStringLessThan, NoContextConstant(), lhs, + rhs); break; case Operation::kLessThanOrEqual: - TailCallRuntime(Runtime::kStringLessThanOrEqual, context, lhs, rhs); + TailCallRuntime(Runtime::kStringLessThanOrEqual, NoContextConstant(), + lhs, rhs); break; case Operation::kGreaterThan: - TailCallRuntime(Runtime::kStringGreaterThan, context, lhs, rhs); + TailCallRuntime(Runtime::kStringGreaterThan, NoContextConstant(), lhs, + rhs); break; case Operation::kGreaterThanOrEqual: - TailCallRuntime(Runtime::kStringGreaterThanOrEqual, context, lhs, rhs); + TailCallRuntime(Runtime::kStringGreaterThanOrEqual, NoContextConstant(), + lhs, rhs); break; default: UNREACHABLE(); @@ -494,41 +474,33 @@ void StringBuiltinsAssembler::GenerateStringRelationalComparison(Node* context, } TF_BUILTIN(StringEqual, StringBuiltinsAssembler) { - Node* context = Parameter(Descriptor::kContext); - Node* left = Parameter(Descriptor::kLeft); - Node* right = Parameter(Descriptor::kRight); - GenerateStringEqual(context, left, right); + TNode<String> left = CAST(Parameter(Descriptor::kLeft)); + TNode<String> right = CAST(Parameter(Descriptor::kRight)); + GenerateStringEqual(left, right); } TF_BUILTIN(StringLessThan, StringBuiltinsAssembler) { - Node* context = Parameter(Descriptor::kContext); - Node* left = Parameter(Descriptor::kLeft); - Node* right = Parameter(Descriptor::kRight); - GenerateStringRelationalComparison(context, left, right, - Operation::kLessThan); + TNode<String> left = CAST(Parameter(Descriptor::kLeft)); + TNode<String> right = CAST(Parameter(Descriptor::kRight)); + GenerateStringRelationalComparison(left, right, Operation::kLessThan); } TF_BUILTIN(StringLessThanOrEqual, StringBuiltinsAssembler) { - Node* context = Parameter(Descriptor::kContext); - Node* left = Parameter(Descriptor::kLeft); - Node* right = Parameter(Descriptor::kRight); - GenerateStringRelationalComparison(context, left, right, - Operation::kLessThanOrEqual); + TNode<String> left = CAST(Parameter(Descriptor::kLeft)); + TNode<String> right = CAST(Parameter(Descriptor::kRight)); + GenerateStringRelationalComparison(left, right, Operation::kLessThanOrEqual); } TF_BUILTIN(StringGreaterThan, StringBuiltinsAssembler) { - Node* context = Parameter(Descriptor::kContext); - Node* left = Parameter(Descriptor::kLeft); - Node* right = Parameter(Descriptor::kRight); - GenerateStringRelationalComparison(context, left, right, - Operation::kGreaterThan); + TNode<String> left = CAST(Parameter(Descriptor::kLeft)); + TNode<String> right = CAST(Parameter(Descriptor::kRight)); + GenerateStringRelationalComparison(left, right, Operation::kGreaterThan); } TF_BUILTIN(StringGreaterThanOrEqual, StringBuiltinsAssembler) { - Node* context = Parameter(Descriptor::kContext); - Node* left = Parameter(Descriptor::kLeft); - Node* right = Parameter(Descriptor::kRight); - GenerateStringRelationalComparison(context, left, right, + TNode<String> left = CAST(Parameter(Descriptor::kLeft)); + TNode<String> right = CAST(Parameter(Descriptor::kRight)); + GenerateStringRelationalComparison(left, right, Operation::kGreaterThanOrEqual); } @@ -598,11 +570,11 @@ TF_BUILTIN(StringFromCharCode, CodeStubAssembler) { // Single argument case, perform fast single character string cache lookup // for one-byte code units, or fall back to creating a single character // string on the fly otherwise. - Node* code = arguments.AtIndex(0); + TNode<Object> code = arguments.AtIndex(0); Node* code32 = TruncateTaggedToWord32(context, code); TNode<Int32T> code16 = Signed(Word32And(code32, Int32Constant(String::kMaxUtf16CodeUnit))); - Node* result = StringFromSingleCharCode(code16); + TNode<String> result = StringFromSingleCharCode(code16); arguments.PopAndReturn(result); } @@ -611,7 +583,7 @@ TF_BUILTIN(StringFromCharCode, CodeStubAssembler) { { Label two_byte(this); // Assume that the resulting string contains only one-byte characters. - Node* one_byte_result = AllocateSeqOneByteString(context, Unsigned(argc)); + TNode<String> one_byte_result = AllocateSeqOneByteString(Unsigned(argc)); TVARIABLE(IntPtrT, var_max_index); var_max_index = IntPtrConstant(0); @@ -630,7 +602,7 @@ TF_BUILTIN(StringFromCharCode, CodeStubAssembler) { &two_byte); // The {code16} fits into the SeqOneByteString {one_byte_result}. - Node* offset = ElementOffsetFromIndex( + TNode<IntPtrT> offset = ElementOffsetFromIndex( var_max_index.value(), UINT8_ELEMENTS, CodeStubAssembler::INTPTR_PARAMETERS, SeqOneByteString::kHeaderSize - kHeapObjectTag); @@ -645,7 +617,7 @@ TF_BUILTIN(StringFromCharCode, CodeStubAssembler) { // At least one of the characters in the string requires a 16-bit // representation. Allocate a SeqTwoByteString to hold the resulting // string. - Node* two_byte_result = AllocateSeqTwoByteString(context, Unsigned(argc)); + TNode<String> two_byte_result = AllocateSeqTwoByteString(Unsigned(argc)); // Copy the characters that have already been put in the 8-bit string into // their corresponding positions in the new 16-bit string. @@ -655,7 +627,7 @@ TF_BUILTIN(StringFromCharCode, CodeStubAssembler) { String::TWO_BYTE_ENCODING); // Write the character that caused the 8-bit to 16-bit fault. - Node* max_index_offset = + TNode<IntPtrT> max_index_offset = ElementOffsetFromIndex(var_max_index.value(), UINT16_ELEMENTS, CodeStubAssembler::INTPTR_PARAMETERS, SeqTwoByteString::kHeaderSize - kHeapObjectTag); @@ -670,10 +642,10 @@ TF_BUILTIN(StringFromCharCode, CodeStubAssembler) { vars, [this, context, two_byte_result, &var_max_index](Node* arg) { Node* code32 = TruncateTaggedToWord32(context, arg); - Node* code16 = + TNode<Word32T> code16 = Word32And(code32, Int32Constant(String::kMaxUtf16CodeUnit)); - Node* offset = ElementOffsetFromIndex( + TNode<IntPtrT> offset = ElementOffsetFromIndex( var_max_index.value(), UINT16_ELEMENTS, CodeStubAssembler::INTPTR_PARAMETERS, SeqTwoByteString::kHeaderSize - kHeapObjectTag); @@ -688,12 +660,9 @@ TF_BUILTIN(StringFromCharCode, CodeStubAssembler) { } void StringBuiltinsAssembler::StringIndexOf( - Node* const subject_string, Node* const search_string, Node* const position, - const std::function<void(Node*)>& f_return) { - CSA_ASSERT(this, IsString(subject_string)); - CSA_ASSERT(this, IsString(search_string)); - CSA_ASSERT(this, TaggedIsSmi(position)); - + TNode<String> const subject_string, TNode<String> const search_string, + TNode<Smi> const position, + const std::function<void(TNode<Smi>)>& f_return) { TNode<IntPtrT> const int_zero = IntPtrConstant(0); TNode<IntPtrT> const search_length = LoadStringLengthAsWord(search_string); TNode<IntPtrT> const subject_length = LoadStringLengthAsWord(subject_string); @@ -712,7 +681,7 @@ void StringBuiltinsAssembler::StringIndexOf( // If the string pointers are identical, we can just return 0. Note that this // implies {start_position} == 0 since we've passed the check above. Label return_zero(this); - GotoIf(WordEqual(subject_string, search_string), &return_zero); + GotoIf(TaggedEqual(subject_string, search_string), &return_zero); // Try to unpack subject and search strings. Bail to runtime if either needs // to be flattened. @@ -725,13 +694,13 @@ void StringBuiltinsAssembler::StringIndexOf( search_to_direct.TryToDirect(&call_runtime_unchecked); // Load pointers to string data. - Node* const subject_ptr = + TNode<RawPtrT> const subject_ptr = subject_to_direct.PointerToData(&call_runtime_unchecked); - Node* const search_ptr = + TNode<RawPtrT> const search_ptr = search_to_direct.PointerToData(&call_runtime_unchecked); - Node* const subject_offset = subject_to_direct.offset(); - Node* const search_offset = search_to_direct.offset(); + TNode<IntPtrT> const subject_offset = subject_to_direct.offset(); + TNode<IntPtrT> const search_offset = search_to_direct.offset(); // Like String::IndexOf, the actual matching is done by the optimized // SearchString method in string-search.h. Dispatch based on string instance @@ -754,9 +723,9 @@ void StringBuiltinsAssembler::StringIndexOf( BIND(&one_one); { - Node* const adjusted_subject_ptr = PointerToStringDataAtIndex( + TNode<IntPtrT> const adjusted_subject_ptr = PointerToStringDataAtIndex( subject_ptr, subject_offset, String::ONE_BYTE_ENCODING); - Node* const adjusted_search_ptr = PointerToStringDataAtIndex( + TNode<IntPtrT> const adjusted_search_ptr = PointerToStringDataAtIndex( search_ptr, search_offset, String::ONE_BYTE_ENCODING); Label direct_memchr_call(this), generic_fast_path(this); @@ -767,20 +736,22 @@ void StringBuiltinsAssembler::StringIndexOf( // search strings. BIND(&direct_memchr_call); { - Node* const string_addr = IntPtrAdd(adjusted_subject_ptr, start_position); - Node* const search_length = IntPtrSub(subject_length, start_position); - Node* const search_byte = + TNode<IntPtrT> const string_addr = + IntPtrAdd(adjusted_subject_ptr, start_position); + TNode<IntPtrT> const search_length = + IntPtrSub(subject_length, start_position); + TNode<IntPtrT> const search_byte = ChangeInt32ToIntPtr(Load(MachineType::Uint8(), adjusted_search_ptr)); - Node* const memchr = + TNode<ExternalReference> const memchr = ExternalConstant(ExternalReference::libc_memchr_function()); - Node* const result_address = + TNode<IntPtrT> const result_address = UncheckedCast<IntPtrT>( 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)); + std::make_pair(MachineType::UintPtr(), search_length))); GotoIf(WordEqual(result_address, int_zero), &return_minus_1); - Node* const result_index = + TNode<IntPtrT> const result_index = IntPtrAdd(IntPtrSub(result_address, string_addr), start_position); f_return(SmiTag(result_index)); } @@ -796,9 +767,9 @@ void StringBuiltinsAssembler::StringIndexOf( BIND(&one_two); { - Node* const adjusted_subject_ptr = PointerToStringDataAtIndex( + TNode<IntPtrT> const adjusted_subject_ptr = PointerToStringDataAtIndex( subject_ptr, subject_offset, String::ONE_BYTE_ENCODING); - Node* const adjusted_search_ptr = PointerToStringDataAtIndex( + TNode<IntPtrT> const adjusted_search_ptr = PointerToStringDataAtIndex( search_ptr, search_offset, String::TWO_BYTE_ENCODING); Node* const result = CallSearchStringRaw<onebyte_t, twobyte_t>( @@ -809,9 +780,9 @@ void StringBuiltinsAssembler::StringIndexOf( BIND(&two_one); { - Node* const adjusted_subject_ptr = PointerToStringDataAtIndex( + TNode<IntPtrT> const adjusted_subject_ptr = PointerToStringDataAtIndex( subject_ptr, subject_offset, String::TWO_BYTE_ENCODING); - Node* const adjusted_search_ptr = PointerToStringDataAtIndex( + TNode<IntPtrT> const adjusted_search_ptr = PointerToStringDataAtIndex( search_ptr, search_offset, String::ONE_BYTE_ENCODING); Node* const result = CallSearchStringRaw<twobyte_t, onebyte_t>( @@ -822,9 +793,9 @@ void StringBuiltinsAssembler::StringIndexOf( BIND(&two_two); { - Node* const adjusted_subject_ptr = PointerToStringDataAtIndex( + TNode<IntPtrT> const adjusted_subject_ptr = PointerToStringDataAtIndex( subject_ptr, subject_offset, String::TWO_BYTE_ENCODING); - Node* const adjusted_search_ptr = PointerToStringDataAtIndex( + TNode<IntPtrT> const adjusted_search_ptr = PointerToStringDataAtIndex( search_ptr, search_offset, String::TWO_BYTE_ENCODING); Node* const result = CallSearchStringRaw<twobyte_t, twobyte_t>( @@ -850,9 +821,9 @@ void StringBuiltinsAssembler::StringIndexOf( // Simplified version of the runtime call where the types of the arguments // are already known due to type checks in this stub. Comment("Call Runtime Unchecked"); - Node* result = - CallRuntime(Runtime::kStringIndexOfUnchecked, NoContextConstant(), - subject_string, search_string, position); + TNode<Smi> result = + CAST(CallRuntime(Runtime::kStringIndexOfUnchecked, NoContextConstant(), + subject_string, search_string, position)); f_return(result); } } @@ -861,11 +832,11 @@ void StringBuiltinsAssembler::StringIndexOf( // #sec-string.prototype.indexof // Unchecked helper for builtins lowering. TF_BUILTIN(StringIndexOf, StringBuiltinsAssembler) { - Node* receiver = Parameter(Descriptor::kReceiver); - Node* search_string = Parameter(Descriptor::kSearchString); - Node* position = Parameter(Descriptor::kPosition); + TNode<String> receiver = CAST(Parameter(Descriptor::kReceiver)); + TNode<String> search_string = CAST(Parameter(Descriptor::kSearchString)); + TNode<Smi> position = CAST(Parameter(Descriptor::kPosition)); StringIndexOf(receiver, search_string, position, - [this](Node* result) { this->Return(result); }); + [this](TNode<Smi> result) { this->Return(result); }); } // ES6 String.prototype.includes(searchString [, position]) @@ -890,10 +861,10 @@ void StringIncludesIndexOfAssembler::Generate(SearchVariant variant, TNode<IntPtrT> argc, TNode<Context> context) { CodeStubArguments arguments(this, argc); - Node* const receiver = arguments.GetReceiver(); + TNode<Object> const receiver = arguments.GetReceiver(); - VARIABLE(var_search_string, MachineRepresentation::kTagged); - VARIABLE(var_position, MachineRepresentation::kTagged); + TVARIABLE(Object, var_search_string); + TVARIABLE(Object, var_position); Label argc_1(this), argc_2(this), call_runtime(this, Label::kDeferred), fast_path(this); @@ -902,43 +873,45 @@ void StringIncludesIndexOfAssembler::Generate(SearchVariant variant, { Comment("0 Argument case"); CSA_ASSERT(this, IntPtrEqual(argc, IntPtrConstant(0))); - Node* const undefined = UndefinedConstant(); - var_search_string.Bind(undefined); - var_position.Bind(undefined); + TNode<Oddball> undefined = UndefinedConstant(); + var_search_string = undefined; + var_position = undefined; Goto(&call_runtime); } BIND(&argc_1); { Comment("1 Argument case"); - var_search_string.Bind(arguments.AtIndex(0)); - var_position.Bind(SmiConstant(0)); + var_search_string = arguments.AtIndex(0); + var_position = SmiConstant(0); Goto(&fast_path); } BIND(&argc_2); { Comment("2 Argument case"); - var_search_string.Bind(arguments.AtIndex(0)); - var_position.Bind(arguments.AtIndex(1)); + var_search_string = arguments.AtIndex(0); + var_position = arguments.AtIndex(1); GotoIfNot(TaggedIsSmi(var_position.value()), &call_runtime); Goto(&fast_path); } BIND(&fast_path); { Comment("Fast Path"); - Node* const search = var_search_string.value(); - Node* const position = var_position.value(); + TNode<Object> const search = var_search_string.value(); + TNode<Smi> const position = CAST(var_position.value()); GotoIf(TaggedIsSmi(receiver), &call_runtime); GotoIf(TaggedIsSmi(search), &call_runtime); - GotoIfNot(IsString(receiver), &call_runtime); - GotoIfNot(IsString(search), &call_runtime); - - StringIndexOf(receiver, search, position, [&](Node* result) { - CSA_ASSERT(this, TaggedIsSmi(result)); - arguments.PopAndReturn((variant == kIndexOf) - ? result - : SelectBooleanConstant(SmiGreaterThanOrEqual( - CAST(result), SmiConstant(0)))); - }); + GotoIfNot(IsString(CAST(receiver)), &call_runtime); + GotoIfNot(IsString(CAST(search)), &call_runtime); + + StringIndexOf(CAST(receiver), CAST(search), position, + [&](TNode<Smi> result) { + if (variant == kIndexOf) { + arguments.PopAndReturn(result); + } else { + arguments.PopAndReturn(SelectBooleanConstant( + SmiGreaterThanOrEqual(result, SmiConstant(0)))); + } + }); } BIND(&call_runtime); { @@ -946,7 +919,7 @@ void StringIncludesIndexOfAssembler::Generate(SearchVariant variant, Runtime::FunctionId runtime = variant == kIndexOf ? Runtime::kStringIndexOf : Runtime::kStringIncludes; - Node* const result = + TNode<Object> const result = CallRuntime(runtime, context, receiver, var_search_string.value(), var_position.value()); arguments.PopAndReturn(result); @@ -955,7 +928,8 @@ void StringIncludesIndexOfAssembler::Generate(SearchVariant variant, void StringBuiltinsAssembler::MaybeCallFunctionAtSymbol( Node* const context, Node* const object, Node* const maybe_string, - Handle<Symbol> symbol, DescriptorIndexAndName symbol_index, + Handle<Symbol> symbol, + DescriptorIndexNameValue additional_property_to_check, const NodeFunction0& regexp_call, const NodeFunction1& generic_call) { Label out(this); @@ -972,9 +946,17 @@ void StringBuiltinsAssembler::MaybeCallFunctionAtSymbol( GotoIf(TaggedIsSmi(maybe_string), &slow_lookup); GotoIfNot(IsString(maybe_string), &slow_lookup); + // Note we don't run a full (= permissive) check here, because passing the + // check implies calling the fast variants of target builtins, which assume + // we've already made their appropriate fast path checks. This is not the + // case though; e.g.: some of the target builtins access flag getters. + // TODO(jgruber): Handle slow flag accesses on the fast path and make this + // permissive. RegExpBuiltinsAssembler regexp_asm(state()); - regexp_asm.BranchIfFastRegExp(context, object, LoadMap(object), - symbol_index, &stub_call, &slow_lookup); + regexp_asm.BranchIfFastRegExp( + CAST(context), CAST(object), LoadMap(object), + PrototypeCheckAssembler::kCheckPrototypePropertyConstness, + additional_property_to_check, &stub_call, &slow_lookup); BIND(&stub_call); // TODO(jgruber): Add a no-JS scope once it exists. @@ -993,7 +975,7 @@ void StringBuiltinsAssembler::MaybeCallFunctionAtSymbol( // We handle the former by jumping to {out} for null values as well, while // the latter is already handled by the Call({maybe_func}) operation. - Node* const maybe_func = GetProperty(context, object, symbol); + TNode<Object> const maybe_func = GetProperty(context, object, symbol); GotoIf(IsUndefined(maybe_func), &out); GotoIf(IsNull(maybe_func), &out); @@ -1041,10 +1023,10 @@ compiler::Node* StringBuiltinsAssembler::GetSubstitution( { CSA_ASSERT(this, TaggedIsPositiveSmi(dollar_index)); - Node* const matched = + TNode<Object> const matched = CallBuiltin(Builtins::kStringSubstring, context, subject_string, SmiUntag(match_start_index), SmiUntag(match_end_index)); - Node* const replacement_string = + TNode<Object> const replacement_string = CallRuntime(Runtime::kGetSubstitution, context, matched, subject_string, match_start_index, replace_string, dollar_index); var_result.Bind(replacement_string); @@ -1073,8 +1055,9 @@ TF_BUILTIN(StringPrototypeReplace, StringBuiltinsAssembler) { MaybeCallFunctionAtSymbol( context, search, receiver, isolate()->factory()->replace_symbol(), - DescriptorIndexAndName{JSRegExp::kSymbolReplaceFunctionDescriptorIndex, - RootIndex::kreplace_symbol}, + DescriptorIndexNameValue{JSRegExp::kSymbolReplaceFunctionDescriptorIndex, + RootIndex::kreplace_symbol, + Context::REGEXP_REPLACE_FUNCTION_INDEX}, [=]() { Return(CallBuiltin(Builtins::kRegExpReplace, context, search, receiver, replace)); @@ -1102,7 +1085,8 @@ TF_BUILTIN(StringPrototypeReplace, StringBuiltinsAssembler) { GotoIf(TaggedIsSmi(replace), &next); GotoIfNot(IsString(replace), &next); - Node* const subject_instance_type = LoadInstanceType(subject_string); + TNode<Uint16T> const subject_instance_type = + LoadInstanceType(subject_string); GotoIfNot(IsConsStringInstanceType(subject_instance_type), &next); GotoIf(TaggedIsPositiveSmi(IndexOfDollarChar(context, replace)), &next); @@ -1160,7 +1144,7 @@ TF_BUILTIN(StringPrototypeReplace, StringBuiltinsAssembler) { Label next(this); GotoIf(SmiEqual(match_start_index, smi_zero), &next); - Node* const prefix = + TNode<Object> const prefix = CallBuiltin(Builtins::kStringSubstring, context, subject_string, IntPtrConstant(0), SmiUntag(match_start_index)); var_result.Bind(prefix); @@ -1182,7 +1166,8 @@ TF_BUILTIN(StringPrototypeReplace, StringBuiltinsAssembler) { Node* const replacement = CallJS(call_callable, context, replace, UndefinedConstant(), search_string, match_start_index, subject_string); - Node* const replacement_string = ToString_Inline(context, replacement); + TNode<String> const replacement_string = + ToString_Inline(context, replacement); var_result.Bind(CallBuiltin(Builtins::kStringAdd_CheckNone, context, var_result.value(), replacement_string)); Goto(&out); @@ -1190,7 +1175,7 @@ TF_BUILTIN(StringPrototypeReplace, StringBuiltinsAssembler) { BIND(&if_notcallablereplace); { - Node* const replace_string = ToString_Inline(context, replace); + TNode<String> const replace_string = ToString_Inline(context, replace); Node* const replacement = GetSubstitution(context, subject_string, match_start_index, match_end_index, replace_string); @@ -1201,11 +1186,11 @@ TF_BUILTIN(StringPrototypeReplace, StringBuiltinsAssembler) { BIND(&out); { - Node* const suffix = + TNode<Object> const suffix = CallBuiltin(Builtins::kStringSubstring, context, subject_string, SmiUntag(match_end_index), subject_length); - Node* const result = CallBuiltin(Builtins::kStringAdd_CheckNone, context, - var_result.value(), suffix); + TNode<Object> const result = CallBuiltin( + Builtins::kStringAdd_CheckNone, context, var_result.value(), suffix); Return(result); } } @@ -1225,19 +1210,19 @@ class StringMatchSearchAssembler : public StringBuiltinsAssembler { Builtins::Name builtin; Handle<Symbol> symbol; - DescriptorIndexAndName property_to_check; + DescriptorIndexNameValue property_to_check; if (variant == kMatch) { builtin = Builtins::kRegExpMatchFast; symbol = isolate()->factory()->match_symbol(); - property_to_check = - DescriptorIndexAndName{JSRegExp::kSymbolMatchFunctionDescriptorIndex, - RootIndex::kmatch_symbol}; + property_to_check = DescriptorIndexNameValue{ + JSRegExp::kSymbolMatchFunctionDescriptorIndex, + RootIndex::kmatch_symbol, Context::REGEXP_MATCH_FUNCTION_INDEX}; } else { builtin = Builtins::kRegExpSearchFast; symbol = isolate()->factory()->search_symbol(); - property_to_check = - DescriptorIndexAndName{JSRegExp::kSymbolSearchFunctionDescriptorIndex, - RootIndex::ksearch_symbol}; + property_to_check = DescriptorIndexNameValue{ + JSRegExp::kSymbolSearchFunctionDescriptorIndex, + RootIndex::ksearch_symbol, Context::REGEXP_SEARCH_FUNCTION_INDEX}; } RequireObjectCoercible(context, receiver, method_name); @@ -1255,7 +1240,7 @@ class StringMatchSearchAssembler : public StringBuiltinsAssembler { RegExpBuiltinsAssembler regexp_asm(state()); TNode<String> receiver_string = ToString_Inline(context, receiver); - TNode<Context> native_context = LoadNativeContext(context); + TNode<NativeContext> native_context = LoadNativeContext(context); TNode<HeapObject> regexp_function = CAST( LoadContextElement(native_context, Context::REGEXP_FUNCTION_INDEX)); TNode<Map> initial_map = CAST(LoadObjectField( @@ -1263,9 +1248,13 @@ class StringMatchSearchAssembler : public StringBuiltinsAssembler { TNode<Object> regexp = regexp_asm.RegExpCreate( context, initial_map, maybe_regexp, EmptyStringConstant()); + // TODO(jgruber): Handle slow flag accesses on the fast path and make this + // permissive. Label fast_path(this), slow_path(this); - regexp_asm.BranchIfFastRegExp(context, regexp, initial_map, - property_to_check, &fast_path, &slow_path); + regexp_asm.BranchIfFastRegExp( + context, CAST(regexp), initial_map, + PrototypeCheckAssembler::kCheckPrototypePropertyConstness, + property_to_check, &fast_path, &slow_path); BIND(&fast_path); Return(CallBuiltin(builtin, context, regexp, receiver_string)); @@ -1297,7 +1286,7 @@ TF_BUILTIN(StringPrototypeMatchAll, StringBuiltinsAssembler) { TNode<Context> context = CAST(Parameter(Descriptor::kContext)); TNode<Object> maybe_regexp = CAST(Parameter(Descriptor::kRegexp)); TNode<Object> receiver = CAST(Parameter(Descriptor::kReceiver)); - TNode<Context> native_context = LoadNativeContext(context); + TNode<NativeContext> native_context = LoadNativeContext(context); // 1. Let O be ? RequireObjectCoercible(this value). RequireObjectCoercible(context, receiver, method_name); @@ -1320,8 +1309,9 @@ TF_BUILTIN(StringPrototypeMatchAll, StringBuiltinsAssembler) { }; MaybeCallFunctionAtSymbol( context, maybe_regexp, receiver, isolate()->factory()->match_all_symbol(), - DescriptorIndexAndName{JSRegExp::kSymbolMatchAllFunctionDescriptorIndex, - RootIndex::kmatch_all_symbol}, + DescriptorIndexNameValue{JSRegExp::kSymbolMatchAllFunctionDescriptorIndex, + RootIndex::kmatch_all_symbol, + Context::REGEXP_MATCH_ALL_FUNCTION_INDEX}, if_regexp_call, if_generic_call); RegExpMatchAllAssembler regexp_asm(state()); @@ -1340,141 +1330,6 @@ TF_BUILTIN(StringPrototypeMatchAll, StringBuiltinsAssembler) { Return(CallJS(callable, context, match_all_func, rx, s)); } -class StringPadAssembler : public StringBuiltinsAssembler { - public: - explicit StringPadAssembler(compiler::CodeAssemblerState* state) - : StringBuiltinsAssembler(state) {} - - protected: - enum Variant { kStart, kEnd }; - - void Generate(Variant variant, const char* method_name, TNode<IntPtrT> argc, - TNode<Context> context) { - CodeStubArguments arguments(this, argc); - 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(" ")); - TVARIABLE(IntPtrT, var_fill_length, IntPtrConstant(1)); - - Label check_fill(this), dont_pad(this), invalid_string_length(this), - pad(this); - - // If no max_length was provided, return the string. - GotoIf(IntPtrEqual(argc, IntPtrConstant(0)), &dont_pad); - - TNode<Number> const max_length = - ToLength_Inline(context, arguments.AtIndex(0)); - CSA_ASSERT(this, IsNumberNormalized(max_length)); - - // If max_length <= string_length, return the string. - GotoIfNot(TaggedIsSmi(max_length), &check_fill); - Branch(SmiLessThanOrEqual(CAST(max_length), string_length), &dont_pad, - &check_fill); - - BIND(&check_fill); - { - GotoIf(IntPtrEqual(argc, IntPtrConstant(1)), &pad); - Node* const fill = arguments.AtIndex(1); - GotoIf(IsUndefined(fill), &pad); - - var_fill_string = ToString_Inline(context, fill); - var_fill_length = LoadStringLengthAsWord(var_fill_string.value()); - Branch(WordEqual(var_fill_length.value(), IntPtrConstant(0)), &dont_pad, - &pad); - } - - BIND(&pad); - { - CSA_ASSERT(this, - IntPtrGreaterThan(var_fill_length.value(), IntPtrConstant(0))); - - // Throw if max_length is greater than String::kMaxLength. - GotoIfNot(TaggedIsSmi(max_length), &invalid_string_length); - TNode<Smi> smi_max_length = CAST(max_length); - GotoIfNot( - SmiLessThanOrEqual(smi_max_length, SmiConstant(String::kMaxLength)), - &invalid_string_length); - - CSA_ASSERT(this, SmiGreaterThan(smi_max_length, string_length)); - TNode<Smi> const pad_length = SmiSub(smi_max_length, string_length); - - VARIABLE(var_pad, MachineRepresentation::kTagged); - Label single_char_fill(this), multi_char_fill(this), return_result(this); - Branch(IntPtrEqual(var_fill_length.value(), IntPtrConstant(1)), - &single_char_fill, &multi_char_fill); - - // Fast path for a single character fill. No need to calculate number of - // repetitions or remainder. - BIND(&single_char_fill); - { - var_pad.Bind(CallBuiltin(Builtins::kStringRepeat, context, - static_cast<Node*>(var_fill_string.value()), - pad_length)); - Goto(&return_result); - } - BIND(&multi_char_fill); - { - TNode<Int32T> const fill_length_word32 = - TruncateIntPtrToInt32(var_fill_length.value()); - TNode<Int32T> const pad_length_word32 = SmiToInt32(pad_length); - TNode<Int32T> const repetitions_word32 = - Int32Div(pad_length_word32, fill_length_word32); - TNode<Int32T> const remaining_word32 = - Int32Mod(pad_length_word32, fill_length_word32); - - var_pad.Bind(CallBuiltin(Builtins::kStringRepeat, context, - var_fill_string.value(), - SmiFromInt32(repetitions_word32))); - - GotoIfNot(remaining_word32, &return_result); - { - Node* const remainder_string = CallBuiltin( - Builtins::kStringSubstring, context, var_fill_string.value(), - IntPtrConstant(0), ChangeInt32ToIntPtr(remaining_word32)); - var_pad.Bind(CallBuiltin(Builtins::kStringAdd_CheckNone, context, - var_pad.value(), remainder_string)); - Goto(&return_result); - } - } - BIND(&return_result); - CSA_ASSERT(this, - SmiEqual(pad_length, LoadStringLengthAsSmi(var_pad.value()))); - arguments.PopAndReturn( - variant == kStart - ? CallBuiltin(Builtins::kStringAdd_CheckNone, context, - var_pad.value(), receiver_string) - : CallBuiltin(Builtins::kStringAdd_CheckNone, context, - receiver_string, var_pad.value())); - } - BIND(&dont_pad); - arguments.PopAndReturn(receiver_string); - BIND(&invalid_string_length); - { - CallRuntime(Runtime::kThrowInvalidStringLength, context); - Unreachable(); - } - } -}; - -TF_BUILTIN(StringPrototypePadEnd, StringPadAssembler) { - TNode<IntPtrT> argc = - ChangeInt32ToIntPtr(Parameter(Descriptor::kJSActualArgumentsCount)); - TNode<Context> context = CAST(Parameter(Descriptor::kContext)); - - Generate(kEnd, "String.prototype.padEnd", argc, context); -} - -TF_BUILTIN(StringPrototypePadStart, StringPadAssembler) { - TNode<IntPtrT> argc = - ChangeInt32ToIntPtr(Parameter(Descriptor::kJSActualArgumentsCount)); - TNode<Context> context = CAST(Parameter(Descriptor::kContext)); - - Generate(kStart, "String.prototype.padStart", argc, context); -} - // ES6 #sec-string.prototype.search TF_BUILTIN(StringPrototypeSearch, StringMatchSearchAssembler) { TNode<Object> receiver = CAST(Parameter(Descriptor::kReceiver)); @@ -1484,7 +1339,7 @@ TF_BUILTIN(StringPrototypeSearch, StringMatchSearchAssembler) { } TNode<JSArray> StringBuiltinsAssembler::StringToArray( - TNode<Context> context, TNode<String> subject_string, + TNode<NativeContext> context, TNode<String> subject_string, TNode<Smi> subject_length, TNode<Number> limit_number) { CSA_ASSERT(this, SmiGreaterThan(subject_length, SmiConstant(0))); @@ -1492,7 +1347,7 @@ TNode<JSArray> StringBuiltinsAssembler::StringToArray( fill_thehole_and_call_runtime(this, Label::kDeferred); TVARIABLE(JSArray, result_array); - TNode<Int32T> instance_type = LoadInstanceType(subject_string); + TNode<Uint16T> instance_type = LoadInstanceType(subject_string); GotoIfNot(IsOneByteStringInstanceType(instance_type), &call_runtime); // Try to use cached one byte characters. @@ -1508,10 +1363,10 @@ TNode<JSArray> StringBuiltinsAssembler::StringToArray( TNode<FixedArray> elements = CAST(AllocateFixedArray( PACKED_ELEMENTS, length, AllocationFlag::kAllowLargeObjectAllocation)); // Don't allocate anything while {string_data} is live! - TNode<RawPtrT> string_data = UncheckedCast<RawPtrT>( - to_direct.PointerToData(&fill_thehole_and_call_runtime)); + TNode<RawPtrT> string_data = + to_direct.PointerToData(&fill_thehole_and_call_runtime); TNode<IntPtrT> string_data_offset = to_direct.offset(); - TNode<Object> cache = LoadRoot(RootIndex::kSingleCharacterStringCache); + TNode<FixedArray> cache = SingleCharacterStringCacheConstant(); BuildFastLoop( IntPtrConstant(0), length, @@ -1523,8 +1378,8 @@ TNode<JSArray> StringBuiltinsAssembler::StringToArray( TNode<Int32T> char_code = UncheckedCast<Int32T>(Load(MachineType::Uint8(), string_data, IntPtrAdd(index, string_data_offset))); - Node* code_index = ChangeUint32ToWord(char_code); - TNode<Object> entry = LoadFixedArrayElement(CAST(cache), code_index); + TNode<UintPtrT> code_index = ChangeUint32ToWord(char_code); + TNode<Object> entry = LoadFixedArrayElement(cache, code_index); // If we cannot find a char in the cache, fill the hole for the fixed // array, and call runtime. @@ -1562,14 +1417,14 @@ TF_BUILTIN(StringPrototypeSplit, StringBuiltinsAssembler) { const int kSeparatorArg = 0; const int kLimitArg = 1; - Node* const argc = + TNode<IntPtrT> const argc = ChangeInt32ToIntPtr(Parameter(Descriptor::kJSActualArgumentsCount)); CodeStubArguments args(this, argc); TNode<Object> receiver = args.GetReceiver(); - Node* const separator = args.GetOptionalArgumentValue(kSeparatorArg); - Node* const limit = args.GetOptionalArgumentValue(kLimitArg); - TNode<Context> context = CAST(Parameter(Descriptor::kContext)); + TNode<Object> const separator = args.GetOptionalArgumentValue(kSeparatorArg); + TNode<Object> const limit = args.GetOptionalArgumentValue(kLimitArg); + TNode<NativeContext> context = CAST(Parameter(Descriptor::kContext)); TNode<Smi> smi_zero = SmiConstant(0); @@ -1579,8 +1434,9 @@ TF_BUILTIN(StringPrototypeSplit, StringBuiltinsAssembler) { MaybeCallFunctionAtSymbol( context, separator, receiver, isolate()->factory()->split_symbol(), - DescriptorIndexAndName{JSRegExp::kSymbolSplitFunctionDescriptorIndex, - RootIndex::ksplit_symbol}, + DescriptorIndexNameValue{JSRegExp::kSymbolSplitFunctionDescriptorIndex, + RootIndex::ksplit_symbol, + Context::REGEXP_SPLIT_FUNCTION_INDEX}, [&]() { args.PopAndReturn(CallBuiltin(Builtins::kRegExpSplit, context, separator, receiver, limit)); @@ -1597,13 +1453,12 @@ TF_BUILTIN(StringPrototypeSplit, StringBuiltinsAssembler) { TNode<Number> limit_number = Select<Number>( IsUndefined(limit), [=] { return NumberConstant(kMaxUInt32); }, [=] { return ToUint32(context, limit); }); - Node* const separator_string = ToString_Inline(context, separator); + TNode<String> const separator_string = ToString_Inline(context, separator); Label return_empty_array(this); // Shortcut for {limit} == 0. - GotoIf(WordEqual<Object, Object>(limit_number, smi_zero), - &return_empty_array); + GotoIf(TaggedEqual(limit_number, smi_zero), &return_empty_array); // ECMA-262 says that if {separator} is undefined, the result should // be an array of size 1 containing the entire string. @@ -1612,7 +1467,7 @@ TF_BUILTIN(StringPrototypeSplit, StringBuiltinsAssembler) { GotoIfNot(IsUndefined(separator), &next); const ElementsKind kind = PACKED_ELEMENTS; - Node* const native_context = LoadNativeContext(context); + TNode<NativeContext> const native_context = LoadNativeContext(context); TNode<Map> array_map = LoadJSArrayElementsMap(kind, native_context); TNode<Smi> length = SmiConstant(1); @@ -1642,7 +1497,7 @@ TF_BUILTIN(StringPrototypeSplit, StringBuiltinsAssembler) { BIND(&next); } - Node* const result = + TNode<Object> const result = CallRuntime(Runtime::kStringSplit, context, subject_string, separator_string, limit_number); args.PopAndReturn(result); @@ -1650,7 +1505,7 @@ TF_BUILTIN(StringPrototypeSplit, StringBuiltinsAssembler) { BIND(&return_empty_array); { const ElementsKind kind = PACKED_ELEMENTS; - Node* const native_context = LoadNativeContext(context); + TNode<NativeContext> const native_context = LoadNativeContext(context); TNode<Map> array_map = LoadJSArrayElementsMap(kind, native_context); TNode<Smi> length = smi_zero; @@ -1666,7 +1521,7 @@ TF_BUILTIN(StringPrototypeSubstr, StringBuiltinsAssembler) { const int kStartArg = 0; const int kLengthArg = 1; - Node* const argc = + TNode<IntPtrT> const argc = ChangeInt32ToIntPtr(Parameter(Descriptor::kJSActualArgumentsCount)); CodeStubArguments args(this, argc); @@ -1808,10 +1663,11 @@ void StringTrimAssembler::Generate(String::TrimMode mode, ToDirectStringAssembler to_direct(state(), string); to_direct.TryToDirect(&if_runtime); - Node* const string_data = to_direct.PointerToData(&if_runtime); - Node* const instance_type = to_direct.instance_type(); - Node* const is_stringonebyte = IsOneByteStringInstanceType(instance_type); - Node* const string_data_offset = to_direct.offset(); + TNode<RawPtrT> const string_data = to_direct.PointerToData(&if_runtime); + TNode<Int32T> const instance_type = to_direct.instance_type(); + TNode<BoolT> const is_stringonebyte = + IsOneByteStringInstanceType(instance_type); + TNode<IntPtrT> const string_data_offset = to_direct.offset(); TVARIABLE(IntPtrT, var_start, IntPtrConstant(0)); TVARIABLE(IntPtrT, var_end, IntPtrSub(string_length, IntPtrConstant(1))); @@ -1841,8 +1697,8 @@ void StringTrimAssembler::Generate(String::TrimMode mode, void StringTrimAssembler::ScanForNonWhiteSpaceOrLineTerminator( Node* const string_data, Node* const string_data_offset, - Node* const is_stringonebyte, Variable* const var_index, Node* const end, - int increment, Label* const if_none_found) { + Node* const is_stringonebyte, TVariable<IntPtrT>* const var_index, + TNode<IntPtrT> const end, int increment, Label* const if_none_found) { Label if_stringisonebyte(this), out(this); GotoIf(is_stringonebyte, &if_stringisonebyte); @@ -1866,14 +1722,14 @@ void StringTrimAssembler::ScanForNonWhiteSpaceOrLineTerminator( } void StringTrimAssembler::BuildLoop( - Variable* const var_index, Node* const end, int increment, - Label* const if_none_found, Label* const out, + TVariable<IntPtrT>* const var_index, TNode<IntPtrT> const end, + int increment, Label* const if_none_found, Label* const out, const std::function<Node*(Node*)>& get_character) { Label loop(this, var_index); Goto(&loop); BIND(&loop); { - Node* const index = var_index->value(); + TNode<IntPtrT> index = var_index->value(); GotoIf(IntPtrEqual(index, end), if_none_found); GotoIfNotWhiteSpaceOrLineTerminator( UncheckedCast<Uint32T>(get_character(index)), out); @@ -1883,7 +1739,7 @@ void StringTrimAssembler::BuildLoop( } void StringTrimAssembler::GotoIfNotWhiteSpaceOrLineTerminator( - Node* const char_code, Label* const if_not_whitespace) { + TNode<Word32T> const char_code, Label* const if_not_whitespace) { Label out(this); // 0x0020 - SPACE (Intentionally out of order to fast path a commmon case) @@ -2010,11 +1866,12 @@ void StringBuiltinsAssembler::BranchIfStringPrimitiveWithNoCustomIteration( // Check that the String iterator hasn't been modified in a way that would // affect iteration. - Node* protector_cell = LoadRoot(RootIndex::kStringIteratorProtector); + TNode<PropertyCell> protector_cell = StringIteratorProtectorConstant(); DCHECK(isolate()->heap()->string_iterator_protector().IsPropertyCell()); - Branch(WordEqual(LoadObjectField(protector_cell, PropertyCell::kValueOffset), - SmiConstant(Isolate::kProtectorValid)), - if_true, if_false); + Branch( + TaggedEqual(LoadObjectField(protector_cell, PropertyCell::kValueOffset), + SmiConstant(Isolate::kProtectorValid)), + if_true, if_false); } } // namespace internal diff --git a/deps/v8/src/builtins/builtins-string-gen.h b/deps/v8/src/builtins/builtins-string-gen.h index 679ce0e17f..64d5a77615 100644 --- a/deps/v8/src/builtins/builtins-string-gen.h +++ b/deps/v8/src/builtins/builtins-string-gen.h @@ -19,8 +19,8 @@ class StringBuiltinsAssembler : public CodeStubAssembler { Node* GetSubstitution(Node* context, Node* subject_string, Node* match_start_index, Node* match_end_index, Node* replace_string); - void StringEqual_Core(Node* context, Node* lhs, Node* lhs_instance_type, - Node* rhs, Node* rhs_instance_type, + void StringEqual_Core(SloppyTNode<String> lhs, Node* lhs_instance_type, + SloppyTNode<String> rhs, Node* rhs_instance_type, TNode<IntPtrT> length, Label* if_equal, Label* if_not_equal, Label* if_indirect); void BranchIfStringPrimitiveWithNoCustomIteration(TNode<Object> object, @@ -51,27 +51,29 @@ class StringBuiltinsAssembler : public CodeStubAssembler { Node* const search_ptr, Node* const search_length, Node* const start_position); - Node* PointerToStringDataAtIndex(Node* const string_data, Node* const index, - String::Encoding encoding); + TNode<IntPtrT> PointerToStringDataAtIndex(Node* const string_data, + Node* const index, + String::Encoding encoding); // substr and slice have a common way of handling the {start} argument. void ConvertAndBoundsCheckStartArgument(Node* context, Variable* var_start, Node* start, Node* string_length); - void GenerateStringEqual(Node* context, Node* left, Node* right); - void GenerateStringRelationalComparison(Node* context, Node* left, - Node* right, Operation op); + void GenerateStringEqual(TNode<String> left, TNode<String> right); + void GenerateStringRelationalComparison(TNode<String> left, + TNode<String> right, Operation op); using StringAtAccessor = std::function<TNode<Object>( TNode<String> receiver, TNode<IntPtrT> length, TNode<IntPtrT> index)>; - void StringIndexOf(Node* const subject_string, Node* const search_string, - Node* const position, - const std::function<void(Node*)>& f_return); + void StringIndexOf(TNode<String> const subject_string, + TNode<String> const search_string, + TNode<Smi> const position, + const std::function<void(TNode<Smi>)>& f_return); TNode<Smi> IndexOfDollarChar(Node* const context, Node* const string); - TNode<JSArray> StringToArray(TNode<Context> context, + TNode<JSArray> StringToArray(TNode<NativeContext> context, TNode<String> subject_string, TNode<Smi> subject_length, TNode<Number> limit_number); @@ -94,12 +96,13 @@ class StringBuiltinsAssembler : public CodeStubAssembler { // Important: {regexp_call} may not contain any code that can call into JS. using NodeFunction0 = std::function<void()>; using NodeFunction1 = std::function<void(Node* fn)>; - void MaybeCallFunctionAtSymbol(Node* const context, Node* const object, - Node* const maybe_string, - Handle<Symbol> symbol, - DescriptorIndexAndName symbol_index, - const NodeFunction0& regexp_call, - const NodeFunction1& generic_call); + using DescriptorIndexNameValue = + PrototypeCheckAssembler::DescriptorIndexNameValue; + void MaybeCallFunctionAtSymbol( + Node* const context, Node* const object, Node* const maybe_string, + Handle<Symbol> symbol, + DescriptorIndexNameValue additional_property_to_check, + const NodeFunction0& regexp_call, const NodeFunction1& generic_call); }; class StringIncludesIndexOfAssembler : public StringBuiltinsAssembler { @@ -120,21 +123,19 @@ class StringTrimAssembler : public StringBuiltinsAssembler { : StringBuiltinsAssembler(state) {} V8_EXPORT_PRIVATE void GotoIfNotWhiteSpaceOrLineTerminator( - Node* const char_code, Label* const if_not_whitespace); + TNode<Word32T> const char_code, Label* const if_not_whitespace); protected: void Generate(String::TrimMode mode, const char* method, TNode<IntPtrT> argc, TNode<Context> context); - void ScanForNonWhiteSpaceOrLineTerminator(Node* const string_data, - Node* const string_data_offset, - Node* const is_stringonebyte, - Variable* const var_index, - Node* const end, int increment, - Label* const if_none_found); + void ScanForNonWhiteSpaceOrLineTerminator( + Node* const string_data, Node* const string_data_offset, + Node* const is_stringonebyte, TVariable<IntPtrT>* const var_index, + TNode<IntPtrT> const end, int increment, Label* const if_none_found); - void BuildLoop(Variable* const var_index, Node* const end, int increment, - Label* const if_none_found, Label* const out, + void BuildLoop(TVariable<IntPtrT>* const var_index, TNode<IntPtrT> const end, + int increment, Label* const if_none_found, Label* const out, const std::function<Node*(Node*)>& get_character); }; diff --git a/deps/v8/src/builtins/builtins-string.cc b/deps/v8/src/builtins/builtins-string.cc index 74b15cf99b..04a96c7e46 100644 --- a/deps/v8/src/builtins/builtins-string.cc +++ b/deps/v8/src/builtins/builtins-string.cc @@ -208,14 +208,10 @@ BUILTIN(StringPrototypeNormalize) { ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, form, Object::ToString(isolate, form_input)); - if (!(String::Equals(isolate, form, - isolate->factory()->NewStringFromStaticChars("NFC")) || - String::Equals(isolate, form, - isolate->factory()->NewStringFromStaticChars("NFD")) || - String::Equals(isolate, form, - isolate->factory()->NewStringFromStaticChars("NFKC")) || - String::Equals(isolate, form, - isolate->factory()->NewStringFromStaticChars("NFKD")))) { + if (!(String::Equals(isolate, form, isolate->factory()->NFC_string()) || + String::Equals(isolate, form, isolate->factory()->NFD_string()) || + String::Equals(isolate, form, isolate->factory()->NFKC_string()) || + String::Equals(isolate, form, isolate->factory()->NFKD_string()))) { Handle<String> valid_forms = isolate->factory()->NewStringFromStaticChars("NFC, NFD, NFKC, NFKD"); THROW_NEW_ERROR_RETURN_FAILURE( diff --git a/deps/v8/src/builtins/builtins-symbol-gen.cc b/deps/v8/src/builtins/builtins-symbol-gen.cc index 610a8baeb3..cb1ee28501 100644 --- a/deps/v8/src/builtins/builtins-symbol-gen.cc +++ b/deps/v8/src/builtins/builtins-symbol-gen.cc @@ -16,9 +16,10 @@ TF_BUILTIN(SymbolPrototypeDescriptionGetter, CodeStubAssembler) { TNode<Context> context = CAST(Parameter(Descriptor::kContext)); TNode<Object> receiver = CAST(Parameter(Descriptor::kReceiver)); - Node* value = ToThisValue(context, receiver, PrimitiveType::kSymbol, - "Symbol.prototype.description"); - Node* result = LoadObjectField(value, Symbol::kNameOffset); + TNode<Symbol> value = + CAST(ToThisValue(context, receiver, PrimitiveType::kSymbol, + "Symbol.prototype.description")); + TNode<Object> result = LoadObjectField(value, Symbol::kNameOffset); Return(result); } @@ -27,8 +28,8 @@ TF_BUILTIN(SymbolPrototypeToPrimitive, CodeStubAssembler) { TNode<Context> context = CAST(Parameter(Descriptor::kContext)); TNode<Object> receiver = CAST(Parameter(Descriptor::kReceiver)); - Node* result = ToThisValue(context, receiver, PrimitiveType::kSymbol, - "Symbol.prototype [ @@toPrimitive ]"); + TNode<Object> result = ToThisValue(context, receiver, PrimitiveType::kSymbol, + "Symbol.prototype [ @@toPrimitive ]"); Return(result); } @@ -37,9 +38,10 @@ TF_BUILTIN(SymbolPrototypeToString, CodeStubAssembler) { TNode<Context> context = CAST(Parameter(Descriptor::kContext)); TNode<Object> receiver = CAST(Parameter(Descriptor::kReceiver)); - Node* value = ToThisValue(context, receiver, PrimitiveType::kSymbol, - "Symbol.prototype.toString"); - Node* result = CallRuntime(Runtime::kSymbolDescriptiveString, context, value); + TNode<Object> value = ToThisValue(context, receiver, PrimitiveType::kSymbol, + "Symbol.prototype.toString"); + TNode<Object> result = + CallRuntime(Runtime::kSymbolDescriptiveString, context, value); Return(result); } @@ -48,8 +50,8 @@ TF_BUILTIN(SymbolPrototypeValueOf, CodeStubAssembler) { TNode<Context> context = CAST(Parameter(Descriptor::kContext)); TNode<Object> receiver = CAST(Parameter(Descriptor::kReceiver)); - Node* result = ToThisValue(context, receiver, PrimitiveType::kSymbol, - "Symbol.prototype.valueOf"); + TNode<Object> result = ToThisValue(context, receiver, PrimitiveType::kSymbol, + "Symbol.prototype.valueOf"); Return(result); } diff --git a/deps/v8/src/builtins/builtins-symbol.cc b/deps/v8/src/builtins/builtins-symbol.cc index ea6e594706..e705aec8b0 100644 --- a/deps/v8/src/builtins/builtins-symbol.cc +++ b/deps/v8/src/builtins/builtins-symbol.cc @@ -54,7 +54,7 @@ BUILTIN(SymbolKeyFor) { Handle<Symbol> symbol = Handle<Symbol>::cast(obj); DisallowHeapAllocation no_gc; Object result; - if (symbol->is_public()) { + if (symbol->is_in_public_symbol_table()) { result = symbol->name(); DCHECK(result.IsString()); } else { diff --git a/deps/v8/src/builtins/builtins-typed-array-gen.cc b/deps/v8/src/builtins/builtins-typed-array-gen.cc index 857d33988f..448ff66603 100644 --- a/deps/v8/src/builtins/builtins-typed-array-gen.cc +++ b/deps/v8/src/builtins/builtins-typed-array-gen.cc @@ -35,11 +35,10 @@ void TypedArrayBuiltinsAssembler::SetupTypedArrayEmbedderFields( // TODO(bmeurer,v8:4153): Rename this and maybe fix up the implementation a bit. TNode<JSArrayBuffer> TypedArrayBuiltinsAssembler::AllocateEmptyOnHeapBuffer( TNode<Context> context, TNode<UintPtrT> byte_length) { - TNode<Context> native_context = LoadNativeContext(context); + TNode<NativeContext> native_context = LoadNativeContext(context); TNode<Map> map = CAST(LoadContextElement(native_context, Context::ARRAY_BUFFER_MAP_INDEX)); - TNode<FixedArray> empty_fixed_array = - CAST(LoadRoot(RootIndex::kEmptyFixedArray)); + TNode<FixedArray> empty_fixed_array = EmptyFixedArrayConstant(); TNode<JSArrayBuffer> buffer = UncheckedCast<JSArrayBuffer>( Allocate(JSArrayBuffer::kSizeWithEmbedderFields)); @@ -90,12 +89,12 @@ TF_BUILTIN(TypedArrayConstructor, TypedArrayBuiltinsAssembler) { TNode<Context> context = CAST(Parameter(Descriptor::kContext)); TNode<JSFunction> target = CAST(Parameter(Descriptor::kJSTarget)); TNode<Object> new_target = CAST(Parameter(Descriptor::kJSNewTarget)); - Node* argc = + TNode<IntPtrT> argc = ChangeInt32ToIntPtr(Parameter(Descriptor::kJSActualArgumentsCount)); CodeStubArguments args(this, argc); - Node* arg1 = args.GetOptionalArgumentValue(0); - Node* arg2 = args.GetOptionalArgumentValue(1); - Node* arg3 = args.GetOptionalArgumentValue(2); + TNode<Object> arg1 = args.GetOptionalArgumentValue(0); + TNode<Object> arg2 = args.GetOptionalArgumentValue(1); + TNode<Object> arg3 = args.GetOptionalArgumentValue(2); // If NewTarget is undefined, throw a TypeError exception. // All the TypedArray constructors have this as the first step: @@ -103,8 +102,8 @@ TF_BUILTIN(TypedArrayConstructor, TypedArrayBuiltinsAssembler) { Label throwtypeerror(this, Label::kDeferred); GotoIf(IsUndefined(new_target), &throwtypeerror); - Node* result = CallBuiltin(Builtins::kCreateTypedArray, context, target, - new_target, arg1, arg2, arg3); + TNode<Object> result = CallBuiltin(Builtins::kCreateTypedArray, context, + target, new_target, arg1, arg2, arg3); args.PopAndReturn(result); BIND(&throwtypeerror); @@ -221,7 +220,7 @@ TypedArrayBuiltinsAssembler::GetTypedArrayElementsInfo(TNode<Map> map) { TNode<JSFunction> TypedArrayBuiltinsAssembler::GetDefaultConstructor( TNode<Context> context, TNode<JSTypedArray> exemplar) { TVARIABLE(IntPtrT, context_slot); - TNode<Word32T> elements_kind = LoadElementsKind(exemplar); + TNode<Int32T> elements_kind = LoadElementsKind(exemplar); DispatchTypedArrayByElementsKind( elements_kind, @@ -322,8 +321,8 @@ void TypedArrayBuiltinsAssembler::SetTypedArraySource( TNode<RawPtrT> target_data_ptr = LoadJSTypedArrayBackingStore(target); TNode<RawPtrT> source_data_ptr = LoadJSTypedArrayBackingStore(source); - TNode<Word32T> source_el_kind = LoadElementsKind(source); - TNode<Word32T> target_el_kind = LoadElementsKind(target); + TNode<Int32T> source_el_kind = LoadElementsKind(source); + TNode<Int32T> target_el_kind = LoadElementsKind(target); TNode<IntPtrT> source_el_size = GetTypedArrayElementSize(source_el_kind); TNode<IntPtrT> target_el_size = GetTypedArrayElementSize(target_el_kind); @@ -650,7 +649,7 @@ TF_BUILTIN(TypedArrayPrototypeToStringTag, TypedArrayBuiltinsAssembler) { // that this can be turned into a non-sparse table switch for ideal // performance. BIND(&if_receiverisheapobject); - Node* elements_kind = + TNode<Int32T> elements_kind = Int32Sub(LoadElementsKind(receiver), Int32Constant(FIRST_FIXED_TYPED_ARRAY_ELEMENTS_KIND)); Switch(elements_kind, &return_undefined, elements_kinds, elements_kind_labels, @@ -727,7 +726,7 @@ TF_BUILTIN(TypedArrayOf, TypedArrayBuiltinsAssembler) { TNode<JSTypedArray> new_typed_array = TypedArrayCreateByLength( context, receiver, SmiTag(length), "%TypedArray%.of"); - TNode<Word32T> elements_kind = LoadElementsKind(new_typed_array); + TNode<Int32T> elements_kind = LoadElementsKind(new_typed_array); // 6. Let k be 0. // 7. Repeat, while k < len @@ -858,17 +857,16 @@ TF_BUILTIN(TypedArrayFrom, TypedArrayBuiltinsAssembler) { TNode<SharedFunctionInfo> shared_info = LoadObjectField<SharedFunctionInfo>( CAST(iterator_fn), JSFunction::kSharedFunctionInfoOffset); GotoIfNot( - WordEqual(LoadObjectField(shared_info, - SharedFunctionInfo::kFunctionDataOffset), - SmiConstant(Builtins::kTypedArrayPrototypeValues)), + TaggedEqual(LoadObjectField(shared_info, + SharedFunctionInfo::kFunctionDataOffset), + SmiConstant(Builtins::kTypedArrayPrototypeValues)), &check_iterator); // Check that the ArrayIterator prototype's "next" method hasn't been // overridden - TNode<PropertyCell> protector_cell = - CAST(LoadRoot(RootIndex::kArrayIteratorProtector)); + TNode<PropertyCell> protector_cell = ArrayIteratorProtectorConstant(); GotoIfNot( - WordEqual(LoadObjectField(protector_cell, PropertyCell::kValueOffset), - SmiConstant(Isolate::kProtectorValid)), + TaggedEqual(LoadObjectField(protector_cell, PropertyCell::kValueOffset), + SmiConstant(Isolate::kProtectorValid)), &check_iterator); // Source is a TypedArray with unmodified iterator behavior. Use the @@ -895,7 +893,7 @@ TF_BUILTIN(TypedArrayFrom, TypedArrayBuiltinsAssembler) { // This is not a spec'd limit, so it doesn't particularly matter when we // throw the range error for typed array length > MaxSmi. - TNode<Object> raw_length = LoadJSArrayLength(values); + TNode<Number> raw_length = LoadJSArrayLength(values); GotoIfNot(TaggedIsSmi(raw_length), &if_length_not_smi); final_length = CAST(raw_length); @@ -949,7 +947,7 @@ TF_BUILTIN(TypedArrayFrom, TypedArrayBuiltinsAssembler) { } BIND(&slow_path); - TNode<Word32T> elements_kind = LoadElementsKind(target_obj.value()); + TNode<Int32T> elements_kind = LoadElementsKind(target_obj.value()); // 7e/13 : Copy the elements BuildFastLoop( diff --git a/deps/v8/src/builtins/builtins-wasm-gen.cc b/deps/v8/src/builtins/builtins-wasm-gen.cc index 0b86d35853..12270495c1 100644 --- a/deps/v8/src/builtins/builtins-wasm-gen.cc +++ b/deps/v8/src/builtins/builtins-wasm-gen.cc @@ -4,6 +4,7 @@ #include "src/builtins/builtins-utils-gen.h" #include "src/codegen/code-stub-assembler.h" +#include "src/codegen/interface-descriptors.h" #include "src/objects/objects-inl.h" #include "src/wasm/wasm-objects.h" #include "src/wasm/wasm-opcodes.h" @@ -46,10 +47,16 @@ class WasmBuiltinsAssembler : public CodeStubAssembler { } TNode<Code> LoadCEntryFromInstance(TNode<Object> instance) { - return UncheckedCast<Code>( - Load(MachineType::AnyTagged(), instance, - IntPtrConstant(WasmInstanceObject::kCEntryStubOffset - + TNode<IntPtrT> isolate_root = UncheckedCast<IntPtrT>( + Load(MachineType::Pointer(), instance, + IntPtrConstant(WasmInstanceObject::kIsolateRootOffset - kHeapObjectTag))); + auto centry_id = + Builtins::kCEntry_Return1_DontSaveFPRegs_ArgvOnStack_NoBuiltinExit; + TNode<Code> target = UncheckedCast<Code>( + Load(MachineType::TaggedPointer(), isolate_root, + IntPtrConstant(IsolateData::builtin_slot_offset(centry_id)))); + return target; } }; @@ -58,14 +65,6 @@ TF_BUILTIN(WasmAllocateHeapNumber, WasmBuiltinsAssembler) { TailCallStub(AllocateHeapNumberDescriptor(), target, NoContextConstant()); } -TF_BUILTIN(WasmCallJavaScript, WasmBuiltinsAssembler) { - TNode<Object> context = UncheckedParameter(Descriptor::kContext); - TNode<Object> function = UncheckedParameter(Descriptor::kFunction); - TNode<Object> argc = UncheckedParameter(Descriptor::kActualArgumentsCount); - TNode<Code> target = LoadBuiltinFromFrame(Builtins::kCall_ReceiverIsAny); - TailCallStub(CallTrampolineDescriptor{}, target, context, function, argc); -} - TF_BUILTIN(WasmRecordWrite, WasmBuiltinsAssembler) { TNode<Object> object = UncheckedParameter(Descriptor::kObject); TNode<Object> slot = UncheckedParameter(Descriptor::kSlot); @@ -299,6 +298,20 @@ TF_BUILTIN(WasmI64ToBigInt, WasmBuiltinsAssembler) { TailCallStub(I64ToBigIntDescriptor(), target, NoContextConstant(), argument); } +TF_BUILTIN(WasmI32PairToBigInt, WasmBuiltinsAssembler) { + if (!Is32()) { + Unreachable(); + return; + } + + TNode<Code> target = LoadBuiltinFromFrame(Builtins::kI32PairToBigInt); + TNode<IntPtrT> low = UncheckedCast<IntPtrT>(Parameter(Descriptor::kLow)); + TNode<IntPtrT> high = UncheckedCast<IntPtrT>(Parameter(Descriptor::kHigh)); + + TailCallStub(I32PairToBigIntDescriptor(), target, NoContextConstant(), low, + high); +} + TF_BUILTIN(WasmBigIntToI64, WasmBuiltinsAssembler) { if (!Is64()) { Unreachable(); @@ -314,6 +327,21 @@ TF_BUILTIN(WasmBigIntToI64, WasmBuiltinsAssembler) { TailCallStub(BigIntToI64Descriptor(), target, context, argument); } +TF_BUILTIN(WasmBigIntToI32Pair, WasmBuiltinsAssembler) { + if (!Is32()) { + Unreachable(); + return; + } + + TNode<Object> context = + UncheckedCast<Object>(Parameter(Descriptor::kContext)); + TNode<Code> target = LoadBuiltinFromFrame(Builtins::kBigIntToI32Pair); + TNode<IntPtrT> argument = + UncheckedCast<IntPtrT>(Parameter(Descriptor::kArgument)); + + TailCallStub(BigIntToI32PairDescriptor(), target, context, argument); +} + #define DECLARE_ENUM(name) \ TF_BUILTIN(ThrowWasm##name, WasmBuiltinsAssembler) { \ TNode<Object> instance = LoadInstanceFromFrame(); \ diff --git a/deps/v8/src/builtins/builtins-weak-refs.cc b/deps/v8/src/builtins/builtins-weak-refs.cc index 18738d2c48..28fb9c9cbd 100644 --- a/deps/v8/src/builtins/builtins-weak-refs.cc +++ b/deps/v8/src/builtins/builtins-weak-refs.cc @@ -151,8 +151,11 @@ BUILTIN(FinalizationGroupCleanupSome) { // Don't do set_scheduled_for_cleanup(false); we still have the microtask // scheduled and don't want to schedule another one in case the user never // executes microtasks. - JSFinalizationGroup::Cleanup(isolate, finalization_group, callback); - + if (JSFinalizationGroup::Cleanup(isolate, finalization_group, callback) + .IsNothing()) { + DCHECK(isolate->has_pending_exception()); + return ReadOnlyRoots(isolate).exception(); + } return ReadOnlyRoots(isolate).undefined_value(); } diff --git a/deps/v8/src/builtins/builtins.cc b/deps/v8/src/builtins/builtins.cc index ed4a844c98..e5829dd1b3 100644 --- a/deps/v8/src/builtins/builtins.cc +++ b/deps/v8/src/builtins/builtins.cc @@ -158,8 +158,7 @@ int Builtins::GetStackParameterCount(Name name) { } // static -Callable Builtins::CallableFor(Isolate* isolate, Name name) { - Handle<Code> code = isolate->builtins()->builtin_handle(name); +CallInterfaceDescriptor Builtins::CallInterfaceDescriptorFor(Name name) { CallDescriptors::Key key; switch (name) { // This macro is deliberately crafted so as to emit very little code, @@ -176,12 +175,17 @@ Callable Builtins::CallableFor(Isolate* isolate, Name name) { Builtins::Kind kind = Builtins::KindOf(name); DCHECK_NE(BCH, kind); if (kind == TFJ || kind == CPP) { - return Callable(code, JSTrampolineDescriptor{}); + return JSTrampolineDescriptor{}; } UNREACHABLE(); } - CallInterfaceDescriptor descriptor(key); - return Callable(code, descriptor); + return CallInterfaceDescriptor{key}; +} + +// static +Callable Builtins::CallableFor(Isolate* isolate, Name name) { + Handle<Code> code = isolate->builtins()->builtin_handle(name); + return Callable{code, CallInterfaceDescriptorFor(name)}; } // static diff --git a/deps/v8/src/builtins/builtins.h b/deps/v8/src/builtins/builtins.h index f885c6f29f..0b9f2a2b57 100644 --- a/deps/v8/src/builtins/builtins.h +++ b/deps/v8/src/builtins/builtins.h @@ -13,6 +13,7 @@ namespace v8 { namespace internal { class ByteArray; +class CallInterfaceDescriptor; class Callable; template <typename T> class Handle; @@ -92,6 +93,7 @@ class Builtins { V8_EXPORT_PRIVATE Code builtin(int index); V8_EXPORT_PRIVATE Handle<Code> builtin_handle(int index); + static CallInterfaceDescriptor CallInterfaceDescriptorFor(Name name); V8_EXPORT_PRIVATE static Callable CallableFor(Isolate* isolate, Name name); static int GetStackParameterCount(Name name); diff --git a/deps/v8/src/builtins/collections.tq b/deps/v8/src/builtins/collections.tq index b83906d109..47d9ec664a 100644 --- a/deps/v8/src/builtins/collections.tq +++ b/deps/v8/src/builtins/collections.tq @@ -6,7 +6,7 @@ namespace collections { @export - macro LoadKeyValuePairNoSideEffects(implicit context: Context)(o: Object): + macro LoadKeyValuePairNoSideEffects(implicit context: Context)(o: JSAny): KeyValuePair labels MayHaveSideEffects { typeswitch (o) { case (a: FastJSArray): { @@ -28,7 +28,7 @@ namespace collections { Undefined }; } - case (Object): deferred { + case (FixedArrayBase): deferred { unreachable; } } @@ -36,14 +36,14 @@ namespace collections { case (JSReceiver): { goto MayHaveSideEffects; } - case (o: Object): deferred { + case (o: JSAny): deferred { ThrowTypeError(kIteratorValueNotAnObject, o); } } } @export - transitioning macro LoadKeyValuePair(implicit context: Context)(o: Object): + transitioning macro LoadKeyValuePair(implicit context: Context)(o: JSAny): KeyValuePair { try { return LoadKeyValuePairNoSideEffects(o) otherwise Generic; diff --git a/deps/v8/src/builtins/data-view.tq b/deps/v8/src/builtins/data-view.tq index 62a0cc31c3..2cf0609561 100644 --- a/deps/v8/src/builtins/data-view.tq +++ b/deps/v8/src/builtins/data-view.tq @@ -58,11 +58,11 @@ namespace data_view { } } - macro WasNeutered(view: JSArrayBufferView): bool { + macro WasDetached(view: JSArrayBufferView): bool { return IsDetachedBuffer(view.buffer); } - macro ValidateDataView(context: Context, o: Object, method: String): + macro ValidateDataView(context: Context, o: JSAny, method: String): JSDataView { try { return Cast<JSDataView>(o) otherwise CastError; @@ -75,7 +75,7 @@ namespace data_view { // ES6 section 24.2.4.1 get DataView.prototype.buffer javascript builtin DataViewPrototypeGetBuffer( js-implicit context: Context, - receiver: Object)(...arguments): JSArrayBuffer { + receiver: JSAny)(...arguments): JSArrayBuffer { const dataView: JSDataView = ValidateDataView(context, receiver, 'get DataView.prototype.buffer'); return dataView.buffer; @@ -83,12 +83,12 @@ namespace data_view { // ES6 section 24.2.4.2 get DataView.prototype.byteLength javascript builtin DataViewPrototypeGetByteLength( - js-implicit context: Context, receiver: Object)(...arguments): Number { + js-implicit context: Context, receiver: JSAny)(...arguments): Number { const dataView: JSDataView = ValidateDataView( context, receiver, 'get DataView.prototype.byte_length'); - if (WasNeutered(dataView)) { + if (WasDetached(dataView)) { // TODO(bmeurer): According to the ES6 spec, we should throw a TypeError - // here if the JSArrayBuffer of the {dataView} was neutered. + // here if the JSArrayBuffer of the {dataView} was detached. return 0; } return Convert<Number>(dataView.byte_length); @@ -96,12 +96,12 @@ namespace data_view { // ES6 section 24.2.4.3 get DataView.prototype.byteOffset javascript builtin DataViewPrototypeGetByteOffset( - js-implicit context: Context, receiver: Object)(...arguments): Number { + js-implicit context: Context, receiver: JSAny)(...arguments): Number { const dataView: JSDataView = ValidateDataView( context, receiver, 'get DataView.prototype.byte_offset'); - if (WasNeutered(dataView)) { + if (WasDetached(dataView)) { // TODO(bmeurer): According to the ES6 spec, we should throw a TypeError - // here if the JSArrayBuffer of the {dataView} was neutered. + // here if the JSArrayBuffer of the {dataView} was detached. return 0; } return Convert<Number>(dataView.byte_offset); @@ -351,14 +351,14 @@ namespace data_view { return MakeBigInt(lowWord, highWord, signed); } - extern macro ToSmiIndex(Object, Context): Smi + extern macro ToSmiIndex(JSAny, Context): Smi labels RangeError; extern macro DataViewBuiltinsAssembler::DataViewElementSize( constexpr ElementsKind): constexpr int31; transitioning macro DataViewGet( - context: Context, receiver: Object, offset: Object, - requestedLittleEndian: Object, kind: constexpr ElementsKind): Numeric { + context: Context, receiver: JSAny, offset: JSAny, + requestedLittleEndian: JSAny, kind: constexpr ElementsKind): Numeric { const dataView: JSDataView = ValidateDataView(context, receiver, MakeDataViewGetterNameString(kind)); @@ -416,91 +416,91 @@ namespace data_view { } transitioning javascript builtin DataViewPrototypeGetUint8( - js-implicit context: Context, receiver: Object)(...arguments): Object { - const offset: Object = arguments.length > 0 ? arguments[0] : Undefined; + js-implicit context: Context, receiver: JSAny)(...arguments): JSAny { + const offset: JSAny = arguments.length > 0 ? arguments[0] : Undefined; return DataViewGet(context, receiver, offset, Undefined, UINT8_ELEMENTS); } transitioning javascript builtin DataViewPrototypeGetInt8( - js-implicit context: Context, receiver: Object)(...arguments): Object { - const offset: Object = arguments.length > 0 ? arguments[0] : Undefined; + js-implicit context: Context, receiver: JSAny)(...arguments): JSAny { + const offset: JSAny = arguments.length > 0 ? arguments[0] : Undefined; return DataViewGet(context, receiver, offset, Undefined, INT8_ELEMENTS); } transitioning javascript builtin DataViewPrototypeGetUint16( - js-implicit context: Context, receiver: Object)(...arguments): Object { - const offset: Object = arguments.length > 0 ? arguments[0] : Undefined; - const isLittleEndian: Object = + js-implicit context: Context, receiver: JSAny)(...arguments): JSAny { + const offset: JSAny = arguments.length > 0 ? arguments[0] : Undefined; + const isLittleEndian: JSAny = arguments.length > 1 ? arguments[1] : Undefined; return DataViewGet( context, receiver, offset, isLittleEndian, UINT16_ELEMENTS); } transitioning javascript builtin DataViewPrototypeGetInt16( - js-implicit context: Context, receiver: Object)(...arguments): Object { - const offset: Object = arguments.length > 0 ? arguments[0] : Undefined; - const isLittleEndian: Object = + js-implicit context: Context, receiver: JSAny)(...arguments): JSAny { + const offset: JSAny = arguments.length > 0 ? arguments[0] : Undefined; + const isLittleEndian: JSAny = arguments.length > 1 ? arguments[1] : Undefined; return DataViewGet( context, receiver, offset, isLittleEndian, INT16_ELEMENTS); } transitioning javascript builtin DataViewPrototypeGetUint32( - js-implicit context: Context, receiver: Object)(...arguments): Object { - const offset: Object = arguments.length > 0 ? arguments[0] : Undefined; - const isLittleEndian: Object = + js-implicit context: Context, receiver: JSAny)(...arguments): JSAny { + const offset: JSAny = arguments.length > 0 ? arguments[0] : Undefined; + const isLittleEndian: JSAny = arguments.length > 1 ? arguments[1] : Undefined; return DataViewGet( context, receiver, offset, isLittleEndian, UINT32_ELEMENTS); } transitioning javascript builtin DataViewPrototypeGetInt32( - js-implicit context: Context, receiver: Object)(...arguments): Object { - const offset: Object = arguments.length > 0 ? arguments[0] : Undefined; - const isLittleEndian: Object = + js-implicit context: Context, receiver: JSAny)(...arguments): JSAny { + const offset: JSAny = arguments.length > 0 ? arguments[0] : Undefined; + const isLittleEndian: JSAny = arguments.length > 1 ? arguments[1] : Undefined; return DataViewGet( context, receiver, offset, isLittleEndian, INT32_ELEMENTS); } transitioning javascript builtin DataViewPrototypeGetFloat32( - js-implicit context: Context, receiver: Object)(...arguments): Object { - const offset: Object = arguments.length > 0 ? arguments[0] : Undefined; - const isLittleEndian: Object = + js-implicit context: Context, receiver: JSAny)(...arguments): JSAny { + const offset: JSAny = arguments.length > 0 ? arguments[0] : Undefined; + const isLittleEndian: JSAny = arguments.length > 1 ? arguments[1] : Undefined; return DataViewGet( context, receiver, offset, isLittleEndian, FLOAT32_ELEMENTS); } transitioning javascript builtin DataViewPrototypeGetFloat64( - js-implicit context: Context, receiver: Object)(...arguments): Object { - const offset: Object = arguments.length > 0 ? arguments[0] : Undefined; - const isLittleEndian: Object = + js-implicit context: Context, receiver: JSAny)(...arguments): JSAny { + const offset: JSAny = arguments.length > 0 ? arguments[0] : Undefined; + const isLittleEndian: JSAny = arguments.length > 1 ? arguments[1] : Undefined; return DataViewGet( context, receiver, offset, isLittleEndian, FLOAT64_ELEMENTS); } transitioning javascript builtin DataViewPrototypeGetBigUint64( - js-implicit context: Context, receiver: Object)(...arguments): Object { - const offset: Object = arguments.length > 0 ? arguments[0] : Undefined; - const isLittleEndian: Object = + js-implicit context: Context, receiver: JSAny)(...arguments): JSAny { + const offset: JSAny = arguments.length > 0 ? arguments[0] : Undefined; + const isLittleEndian: JSAny = arguments.length > 1 ? arguments[1] : Undefined; return DataViewGet( context, receiver, offset, isLittleEndian, BIGUINT64_ELEMENTS); } transitioning javascript builtin DataViewPrototypeGetBigInt64( - js-implicit context: Context, receiver: Object)(...arguments): Object { - const offset: Object = arguments.length > 0 ? arguments[0] : Undefined; - const isLittleEndian: Object = + js-implicit context: Context, receiver: JSAny)(...arguments): JSAny { + const offset: JSAny = arguments.length > 0 ? arguments[0] : Undefined; + const isLittleEndian: JSAny = arguments.length > 1 ? arguments[1] : Undefined; return DataViewGet( context, receiver, offset, isLittleEndian, BIGINT64_ELEMENTS); } - extern macro ToNumber(Context, Object): Number; - extern macro ToBigInt(Context, Object): BigInt; + extern macro ToNumber(Context, JSAny): Number; + extern macro ToBigInt(Context, JSAny): BigInt; extern macro TruncateFloat64ToWord32(float64): uint32; extern macro DataViewBuiltinsAssembler::StoreWord8(RawPtr, uintptr, uint32): @@ -632,8 +632,8 @@ namespace data_view { } transitioning macro DataViewSet( - context: Context, receiver: Object, offset: Object, value: Object, - requestedLittleEndian: Object, kind: constexpr ElementsKind): Object { + context: Context, receiver: JSAny, offset: JSAny, value: JSAny, + requestedLittleEndian: JSAny, kind: constexpr ElementsKind): JSAny { const dataView: JSDataView = ValidateDataView(context, receiver, MakeDataViewSetterNameString(kind)); @@ -718,96 +718,96 @@ namespace data_view { } transitioning javascript builtin DataViewPrototypeSetUint8( - js-implicit context: Context, receiver: Object)(...arguments): Object { - const offset: Object = arguments.length > 0 ? arguments[0] : Undefined; - const value: Object = arguments.length > 1 ? arguments[1] : Undefined; + js-implicit context: Context, receiver: JSAny)(...arguments): JSAny { + const offset: JSAny = arguments.length > 0 ? arguments[0] : Undefined; + const value: JSAny = arguments.length > 1 ? arguments[1] : Undefined; return DataViewSet( context, receiver, offset, value, Undefined, UINT8_ELEMENTS); } transitioning javascript builtin DataViewPrototypeSetInt8( - js-implicit context: Context, receiver: Object)(...arguments): Object { - const offset: Object = arguments.length > 0 ? arguments[0] : Undefined; - const value: Object = arguments.length > 1 ? arguments[1] : Undefined; + js-implicit context: Context, receiver: JSAny)(...arguments): JSAny { + const offset: JSAny = arguments.length > 0 ? arguments[0] : Undefined; + const value: JSAny = arguments.length > 1 ? arguments[1] : Undefined; return DataViewSet( context, receiver, offset, value, Undefined, INT8_ELEMENTS); } transitioning javascript builtin DataViewPrototypeSetUint16( - js-implicit context: Context, receiver: Object)(...arguments): Object { - const offset: Object = arguments.length > 0 ? arguments[0] : Undefined; - const value: Object = arguments.length > 1 ? arguments[1] : Undefined; - const isLittleEndian: Object = + js-implicit context: Context, receiver: JSAny)(...arguments): JSAny { + const offset: JSAny = arguments.length > 0 ? arguments[0] : Undefined; + const value: JSAny = arguments.length > 1 ? arguments[1] : Undefined; + const isLittleEndian: JSAny = arguments.length > 2 ? arguments[2] : Undefined; return DataViewSet( context, receiver, offset, value, isLittleEndian, UINT16_ELEMENTS); } transitioning javascript builtin DataViewPrototypeSetInt16( - js-implicit context: Context, receiver: Object)(...arguments): Object { - const offset: Object = arguments.length > 0 ? arguments[0] : Undefined; - const value: Object = arguments.length > 1 ? arguments[1] : Undefined; - const isLittleEndian: Object = + js-implicit context: Context, receiver: JSAny)(...arguments): JSAny { + const offset: JSAny = arguments.length > 0 ? arguments[0] : Undefined; + const value: JSAny = arguments.length > 1 ? arguments[1] : Undefined; + const isLittleEndian: JSAny = arguments.length > 2 ? arguments[2] : Undefined; return DataViewSet( context, receiver, offset, value, isLittleEndian, INT16_ELEMENTS); } transitioning javascript builtin DataViewPrototypeSetUint32( - js-implicit context: Context, receiver: Object)(...arguments): Object { - const offset: Object = arguments.length > 0 ? arguments[0] : Undefined; - const value: Object = arguments.length > 1 ? arguments[1] : Undefined; - const isLittleEndian: Object = + js-implicit context: Context, receiver: JSAny)(...arguments): JSAny { + const offset: JSAny = arguments.length > 0 ? arguments[0] : Undefined; + const value: JSAny = arguments.length > 1 ? arguments[1] : Undefined; + const isLittleEndian: JSAny = arguments.length > 2 ? arguments[2] : Undefined; return DataViewSet( context, receiver, offset, value, isLittleEndian, UINT32_ELEMENTS); } transitioning javascript builtin DataViewPrototypeSetInt32( - js-implicit context: Context, receiver: Object)(...arguments): Object { - const offset: Object = arguments.length > 0 ? arguments[0] : Undefined; - const value: Object = arguments.length > 1 ? arguments[1] : Undefined; - const isLittleEndian: Object = + js-implicit context: Context, receiver: JSAny)(...arguments): JSAny { + const offset: JSAny = arguments.length > 0 ? arguments[0] : Undefined; + const value: JSAny = arguments.length > 1 ? arguments[1] : Undefined; + const isLittleEndian: JSAny = arguments.length > 2 ? arguments[2] : Undefined; return DataViewSet( context, receiver, offset, value, isLittleEndian, INT32_ELEMENTS); } transitioning javascript builtin DataViewPrototypeSetFloat32( - js-implicit context: Context, receiver: Object)(...arguments): Object { - const offset: Object = arguments.length > 0 ? arguments[0] : Undefined; - const value: Object = arguments.length > 1 ? arguments[1] : Undefined; - const isLittleEndian: Object = + js-implicit context: Context, receiver: JSAny)(...arguments): JSAny { + const offset: JSAny = arguments.length > 0 ? arguments[0] : Undefined; + const value: JSAny = arguments.length > 1 ? arguments[1] : Undefined; + const isLittleEndian: JSAny = arguments.length > 2 ? arguments[2] : Undefined; return DataViewSet( context, receiver, offset, value, isLittleEndian, FLOAT32_ELEMENTS); } transitioning javascript builtin DataViewPrototypeSetFloat64( - js-implicit context: Context, receiver: Object)(...arguments): Object { - const offset: Object = arguments.length > 0 ? arguments[0] : Undefined; - const value: Object = arguments.length > 1 ? arguments[1] : Undefined; - const isLittleEndian: Object = + js-implicit context: Context, receiver: JSAny)(...arguments): JSAny { + const offset: JSAny = arguments.length > 0 ? arguments[0] : Undefined; + const value: JSAny = arguments.length > 1 ? arguments[1] : Undefined; + const isLittleEndian: JSAny = arguments.length > 2 ? arguments[2] : Undefined; return DataViewSet( context, receiver, offset, value, isLittleEndian, FLOAT64_ELEMENTS); } transitioning javascript builtin DataViewPrototypeSetBigUint64( - js-implicit context: Context, receiver: Object)(...arguments): Object { - const offset: Object = arguments.length > 0 ? arguments[0] : Undefined; - const value: Object = arguments.length > 1 ? arguments[1] : Undefined; - const isLittleEndian: Object = + js-implicit context: Context, receiver: JSAny)(...arguments): JSAny { + const offset: JSAny = arguments.length > 0 ? arguments[0] : Undefined; + const value: JSAny = arguments.length > 1 ? arguments[1] : Undefined; + const isLittleEndian: JSAny = arguments.length > 2 ? arguments[2] : Undefined; return DataViewSet( context, receiver, offset, value, isLittleEndian, BIGUINT64_ELEMENTS); } transitioning javascript builtin DataViewPrototypeSetBigInt64( - js-implicit context: Context, receiver: Object)(...arguments): Object { - const offset: Object = arguments.length > 0 ? arguments[0] : Undefined; - const value: Object = arguments.length > 1 ? arguments[1] : Undefined; - const isLittleEndian: Object = + js-implicit context: Context, receiver: JSAny)(...arguments): JSAny { + const offset: JSAny = arguments.length > 0 ? arguments[0] : Undefined; + const value: JSAny = arguments.length > 1 ? arguments[1] : Undefined; + const isLittleEndian: JSAny = arguments.length > 2 ? arguments[2] : Undefined; return DataViewSet( context, receiver, offset, value, isLittleEndian, BIGINT64_ELEMENTS); diff --git a/deps/v8/src/builtins/extras-utils.tq b/deps/v8/src/builtins/extras-utils.tq index 3675fda191..0b48b962e2 100644 --- a/deps/v8/src/builtins/extras-utils.tq +++ b/deps/v8/src/builtins/extras-utils.tq @@ -3,23 +3,22 @@ // found in the LICENSE file. namespace extras_utils { - extern runtime CreatePrivateSymbol(Context, Object): HeapObject; - extern runtime PromiseMarkAsHandled(Context, Object): Undefined; - extern runtime PromiseStatus(Context, Object): Smi; + extern runtime CreatePrivateSymbol(Context, JSAny): PrivateSymbol; + extern runtime PromiseMarkAsHandled(Context, JSAny): Undefined; + extern runtime PromiseStatus(Context, JSAny): Smi; javascript builtin ExtrasUtilsCreatePrivateSymbol( - js-implicit context: Context, - receiver: Object)(...arguments): HeapObject { + js-implicit context: Context, receiver: JSAny)(...arguments): JSAny { return CreatePrivateSymbol(context, arguments[0]); } javascript builtin ExtrasUtilsMarkPromiseAsHandled( - js-implicit context: Context, receiver: Object)(...arguments): Undefined { + js-implicit context: Context, receiver: JSAny)(...arguments): Undefined { return PromiseMarkAsHandled(context, arguments[0]); } javascript builtin ExtrasUtilsPromiseState( - js-implicit context: Context, receiver: Object)(...arguments): Smi { + js-implicit context: Context, receiver: JSAny)(...arguments): Smi { return PromiseStatus(context, arguments[0]); } } diff --git a/deps/v8/src/builtins/frames.tq b/deps/v8/src/builtins/frames.tq index 5559188347..7467381690 100644 --- a/deps/v8/src/builtins/frames.tq +++ b/deps/v8/src/builtins/frames.tq @@ -102,7 +102,7 @@ macro LoadLengthFromAdapterFrame(implicit context: Context)( } operator '==' macro FrameTypeEquals(f1: FrameType, f2: FrameType): bool { - return WordEqual(f1, f2); + return TaggedEqual(f1, f2); } macro Cast<A: type>(implicit context: Context)(o: Frame): A labels CastError; diff --git a/deps/v8/src/builtins/growable-fixed-array-gen.cc b/deps/v8/src/builtins/growable-fixed-array-gen.cc index dd23ac5b5a..4fc051eb14 100644 --- a/deps/v8/src/builtins/growable-fixed-array-gen.cc +++ b/deps/v8/src/builtins/growable-fixed-array-gen.cc @@ -36,7 +36,7 @@ void GrowableFixedArray::Push(TNode<Object> const value) { TNode<JSArray> GrowableFixedArray::ToJSArray(TNode<Context> const context) { const ElementsKind kind = PACKED_ELEMENTS; - TNode<Context> const native_context = LoadNativeContext(context); + TNode<NativeContext> const native_context = LoadNativeContext(context); TNode<Map> const array_map = LoadJSArrayElementsMap(kind, native_context); // Shrink to fit if necessary. diff --git a/deps/v8/src/builtins/ia32/builtins-ia32.cc b/deps/v8/src/builtins/ia32/builtins-ia32.cc index 995be77f75..feabac3b66 100644 --- a/deps/v8/src/builtins/ia32/builtins-ia32.cc +++ b/deps/v8/src/builtins/ia32/builtins-ia32.cc @@ -72,7 +72,7 @@ void Generate_StackOverflowCheck(MacroAssembler* masm, Register num_args, // 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()); + ExternalReference::address_of_real_jslimit(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)); @@ -2676,7 +2676,10 @@ void Builtins::Generate_WasmCompileLazy(MacroAssembler* masm) { __ Push(kWasmCompileLazyFuncIndexRegister); // Load the correct CEntry builtin from the instance object. __ mov(ecx, FieldOperand(kWasmInstanceRegister, - WasmInstanceObject::kCEntryStubOffset)); + WasmInstanceObject::kIsolateRootOffset)); + auto centry_id = + Builtins::kCEntry_Return1_DontSaveFPRegs_ArgvOnStack_NoBuiltinExit; + __ mov(ecx, MemOperand(ecx, IsolateData::builtin_slot_offset(centry_id))); // Initialize the JavaScript context with 0. CEntry will use it to // set the current context on the isolate. __ Move(kContextRegister, Smi::zero()); diff --git a/deps/v8/src/builtins/internal-coverage.tq b/deps/v8/src/builtins/internal-coverage.tq index d96fa924ab..41ec0c36e4 100644 --- a/deps/v8/src/builtins/internal-coverage.tq +++ b/deps/v8/src/builtins/internal-coverage.tq @@ -51,7 +51,7 @@ namespace internal_coverage { } builtin IncBlockCounter(implicit context: Context)( - function: JSFunction, coverageArraySlotIndex: Smi): Object { + function: JSFunction, coverageArraySlotIndex: Smi): Undefined { // It's quite possible that a function contains IncBlockCounter bytecodes, // but no coverage info exists. This happens e.g. by selecting the // best-effort coverage collection mode, which triggers deletion of all diff --git a/deps/v8/src/builtins/iterator.tq b/deps/v8/src/builtins/iterator.tq index b770f1b652..06e8ea539c 100644 --- a/deps/v8/src/builtins/iterator.tq +++ b/deps/v8/src/builtins/iterator.tq @@ -11,13 +11,13 @@ namespace iterator { object: JSReceiver; // iteratorRecord.[[NextMethod]] - next: Object; + next: JSAny; } extern macro IteratorBuiltinsAssembler::GetIteratorMethod( - implicit context: Context)(Object): Object; + implicit context: Context)(JSAny): JSAny; extern macro IteratorBuiltinsAssembler::GetIterator( - implicit context: Context)(Object): IteratorRecord; + implicit context: Context)(JSAny): IteratorRecord; extern macro IteratorBuiltinsAssembler::IteratorStep( implicit context: Context)(IteratorRecord): JSReceiver @@ -27,18 +27,33 @@ namespace iterator { labels Done; extern macro IteratorBuiltinsAssembler::IteratorValue( - implicit context: Context)(JSReceiver): Object; + implicit context: Context)(JSReceiver): JSAny; extern macro IteratorBuiltinsAssembler::IteratorValue( - implicit context: Context)(JSReceiver, Map): Object; + implicit context: Context)(JSReceiver, Map): JSAny; extern macro IteratorBuiltinsAssembler::IteratorCloseOnException( - implicit context: Context)(IteratorRecord, Object): never; + implicit context: Context)(IteratorRecord, JSAny): never; extern macro IteratorBuiltinsAssembler::IterableToList( - implicit context: Context)(Object, Object): JSArray; + implicit context: Context)(JSAny, JSAny): JSArray; extern builtin IterableToListMayPreserveHoles(implicit context: - Context)(Object, Object); + Context)(JSAny, JSAny); extern builtin IterableToListWithSymbolLookup(implicit context: - Context)(Object); + Context)(JSAny); + + transitioning builtin GetIteratorWithFeedback( + context: Context, receiver: JSAny, feedbackSlot: Smi, + feedback: Undefined | FeedbackVector): JSAny { + typeswitch (feedback) { + case (Undefined): { + return GetProperty(receiver, IteratorSymbolConstant()); + } + case (feedback: FeedbackVector): { + return LoadIC( + context, receiver, IteratorSymbolConstant(), feedbackSlot, + feedback); + } + } + } } diff --git a/deps/v8/src/builtins/math.tq b/deps/v8/src/builtins/math.tq index df43b30efc..99a29bd5cb 100644 --- a/deps/v8/src/builtins/math.tq +++ b/deps/v8/src/builtins/math.tq @@ -7,7 +7,7 @@ namespace math { extern macro Float64Acos(float64): float64; transitioning javascript builtin - MathAcos(context: Context, _receiver: Object, x: Object): Number { + MathAcos(js-implicit context: Context)(x: JSAny): Number { const value = Convert<float64>(ToNumber_Inline(context, x)); return Convert<Number>(Float64Acos(value)); } @@ -16,7 +16,7 @@ namespace math { extern macro Float64Acosh(float64): float64; transitioning javascript builtin - MathAcosh(context: Context, _receiver: Object, x: Object): Number { + MathAcosh(js-implicit context: Context)(x: JSAny): Number { const value = Convert<float64>(ToNumber_Inline(context, x)); return Convert<Number>(Float64Acosh(value)); } @@ -25,7 +25,7 @@ namespace math { extern macro Float64Asin(float64): float64; transitioning javascript builtin - MathAsin(context: Context, _receiver: Object, x: Object): Number { + MathAsin(js-implicit context: Context)(x: JSAny): Number { const value = Convert<float64>(ToNumber_Inline(context, x)); return Convert<Number>(Float64Asin(value)); } @@ -34,7 +34,7 @@ namespace math { extern macro Float64Asinh(float64): float64; transitioning javascript builtin - MathAsinh(context: Context, _receiver: Object, x: Object): Number { + MathAsinh(js-implicit context: Context)(x: JSAny): Number { const value = Convert<float64>(ToNumber_Inline(context, x)); return Convert<Number>(Float64Asinh(value)); } @@ -43,7 +43,7 @@ namespace math { extern macro Float64Atan(float64): float64; transitioning javascript builtin - MathAtan(context: Context, _receiver: Object, x: Object): Number { + MathAtan(js-implicit context: Context)(x: JSAny): Number { const value = Convert<float64>(ToNumber_Inline(context, x)); return Convert<Number>(Float64Atan(value)); } @@ -52,7 +52,7 @@ namespace math { extern macro Float64Atan2(float64, float64): float64; transitioning javascript builtin - MathAtan2(context: Context, _receiver: Object, y: Object, x: Object): Number { + MathAtan2(js-implicit context: Context)(y: JSAny, x: JSAny): Number { const yValue = Convert<float64>(ToNumber_Inline(context, y)); const xValue = Convert<float64>(ToNumber_Inline(context, x)); return Convert<Number>(Float64Atan2(yValue, xValue)); @@ -62,7 +62,7 @@ namespace math { extern macro Float64Atanh(float64): float64; transitioning javascript builtin - MathAtanh(context: Context, _receiver: Object, x: Object): Number { + MathAtanh(js-implicit context: Context)(x: JSAny): Number { const value = Convert<float64>(ToNumber_Inline(context, x)); return Convert<Number>(Float64Atanh(value)); } @@ -71,7 +71,7 @@ namespace math { extern macro Float64Cbrt(float64): float64; transitioning javascript builtin - MathCbrt(context: Context, _receiver: Object, x: Object): Number { + MathCbrt(js-implicit context: Context)(x: JSAny): Number { const value = Convert<float64>(ToNumber_Inline(context, x)); return Convert<Number>(Float64Cbrt(value)); } @@ -80,7 +80,7 @@ namespace math { extern macro Word32Clz(int32): int32; transitioning javascript builtin - MathClz32(context: Context, _receiver: Object, x: Object): Number { + MathClz32(js-implicit context: Context)(x: JSAny): Number { const num = ToNumber_Inline(context, x); let value: int32; @@ -100,7 +100,7 @@ namespace math { extern macro Float64Cos(float64): float64; transitioning javascript builtin - MathCos(context: Context, _receiver: Object, x: Object): Number { + MathCos(js-implicit context: Context)(x: JSAny): Number { const value = Convert<float64>(ToNumber_Inline(context, x)); return Convert<Number>(Float64Cos(value)); } @@ -109,7 +109,7 @@ namespace math { extern macro Float64Cosh(float64): float64; transitioning javascript builtin - MathCosh(context: Context, _receiver: Object, x: Object): Number { + MathCosh(js-implicit context: Context)(x: JSAny): Number { const value = Convert<float64>(ToNumber_Inline(context, x)); return Convert<Number>(Float64Cosh(value)); } @@ -118,7 +118,7 @@ namespace math { extern macro Float64Exp(float64): float64; transitioning javascript builtin - MathExp(context: Context, _receiver: Object, x: Object): Number { + MathExp(js-implicit context: Context)(x: JSAny): Number { const value = Convert<float64>(ToNumber_Inline(context, x)); return Convert<Number>(Float64Exp(value)); } @@ -127,14 +127,14 @@ namespace math { extern macro Float64Expm1(float64): float64; transitioning javascript builtin - MathExpm1(context: Context, _receiver: Object, x: Object): Number { + MathExpm1(js-implicit context: Context)(x: JSAny): Number { const value = Convert<float64>(ToNumber_Inline(context, x)); return Convert<Number>(Float64Expm1(value)); } // ES6 #sec-math.fround transitioning javascript builtin - MathFround(context: Context, _receiver: Object, x: Object): Number { + MathFround(js-implicit context: Context)(x: JSAny): Number { const x32 = Convert<float32>(ToNumber_Inline(context, x)); const x64 = Convert<float64>(x32); return Convert<Number>(x64); @@ -144,7 +144,7 @@ namespace math { extern macro Float64Log(float64): float64; transitioning javascript builtin - MathLog(context: Context, _receiver: Object, x: Object): Number { + MathLog(js-implicit context: Context)(x: JSAny): Number { const value = Convert<float64>(ToNumber_Inline(context, x)); return Convert<Number>(Float64Log(value)); } @@ -153,7 +153,7 @@ namespace math { extern macro Float64Log1p(float64): float64; transitioning javascript builtin - MathLog1p(context: Context, _receiver: Object, x: Object): Number { + MathLog1p(js-implicit context: Context)(x: JSAny): Number { const value = Convert<float64>(ToNumber_Inline(context, x)); return Convert<Number>(Float64Log1p(value)); } @@ -162,7 +162,7 @@ namespace math { extern macro Float64Log10(float64): float64; transitioning javascript builtin - MathLog10(context: Context, _receiver: Object, x: Object): Number { + MathLog10(js-implicit context: Context)(x: JSAny): Number { const value = Convert<float64>(ToNumber_Inline(context, x)); return Convert<Number>(Float64Log10(value)); } @@ -171,7 +171,7 @@ namespace math { extern macro Float64Log2(float64): float64; transitioning javascript builtin - MathLog2(context: Context, _receiver: Object, x: Object): Number { + MathLog2(js-implicit context: Context)(x: JSAny): Number { const value = Convert<float64>(ToNumber_Inline(context, x)); return Convert<Number>(Float64Log2(value)); } @@ -180,14 +180,14 @@ namespace math { extern macro Float64Sin(float64): float64; transitioning javascript builtin - MathSin(context: Context, _receiver: Object, x: Object): Number { + MathSin(js-implicit context: Context)(x: JSAny): Number { const value = Convert<float64>(ToNumber_Inline(context, x)); return Convert<Number>(Float64Sin(value)); } // ES6 #sec-math.sign transitioning javascript builtin - MathSign(context: Context, _receiver: Object, x: Object): Number { + MathSign(js-implicit context: Context)(x: JSAny): Number { const num = ToNumber_Inline(context, x); const value = Convert<float64>(num); @@ -204,7 +204,7 @@ namespace math { extern macro Float64Sinh(float64): float64; transitioning javascript builtin - MathSinh(context: Context, _receiver: Object, x: Object): Number { + MathSinh(js-implicit context: Context)(x: JSAny): Number { const value = Convert<float64>(ToNumber_Inline(context, x)); return Convert<Number>(Float64Sinh(value)); } @@ -213,7 +213,7 @@ namespace math { extern macro Float64Sqrt(float64): float64; transitioning javascript builtin - MathSqrt(context: Context, _receiver: Object, x: Object): Number { + MathSqrt(js-implicit context: Context)(x: JSAny): Number { const value = Convert<float64>(ToNumber_Inline(context, x)); return Convert<Number>(Float64Sqrt(value)); } @@ -222,7 +222,7 @@ namespace math { extern macro Float64Tan(float64): float64; transitioning javascript builtin - MathTan(context: Context, _receiver: Object, x: Object): Number { + MathTan(js-implicit context: Context)(x: JSAny): Number { const value = Convert<float64>(ToNumber_Inline(context, x)); return Convert<Number>(Float64Tan(value)); } @@ -231,8 +231,56 @@ namespace math { extern macro Float64Tanh(float64): float64; transitioning javascript builtin - MathTanh(context: Context, _receiver: Object, x: Object): Number { + MathTanh(js-implicit context: Context)(x: JSAny): Number { const value = Convert<float64>(ToNumber_Inline(context, x)); return Convert<Number>(Float64Tanh(value)); } + + extern macro Float64Abs(float64): float64; + + // ES6 #sec-math.hypot + transitioning javascript builtin + MathHypot(js-implicit context: Context, receiver: JSAny)(...arguments): + Number { + const length = arguments.length; + if (length == 0) { + return 0; + } + const absValues = AllocateZeroedFixedDoubleArray(length); + let oneArgIsNaN: bool = false; + let max: float64 = 0; + for (let i: intptr = 0; i < length; ++i) { + const value = Convert<float64>(ToNumber_Inline(context, arguments[i])); + if (Float64IsNaN(value)) { + oneArgIsNaN = true; + } else { + const absValue = Float64Abs(value); + absValues.floats[i] = absValue; + if (absValue > max) { + max = absValue; + } + } + } + if (max == V8_INFINITY) { + return V8_INFINITY; + } else if (oneArgIsNaN) { + return kNaN; + } else if (max == 0) { + return 0; + } + assert(max > 0); + + // Kahan summation to avoid rounding errors. + // Normalize the numbers to the largest one to avoid overflow. + let sum: float64 = 0; + let compensation: float64 = 0; + for (let i: intptr = 0; i < length; ++i) { + const n = absValues.floats[i] / max; + const summand = n * n - compensation; + const preliminary = sum + summand; + compensation = (preliminary - sum) - summand; + sum = preliminary; + } + return Convert<Number>(Float64Sqrt(sum) * max); + } } diff --git a/deps/v8/src/builtins/mips/builtins-mips.cc b/deps/v8/src/builtins/mips/builtins-mips.cc index a359b2436f..d3237a1c38 100644 --- a/deps/v8/src/builtins/mips/builtins-mips.cc +++ b/deps/v8/src/builtins/mips/builtins-mips.cc @@ -84,6 +84,17 @@ static void GenerateTailCallToReturnedCode(MacroAssembler* masm, namespace { +void LoadRealStackLimit(MacroAssembler* masm, Register destination) { + DCHECK(masm->root_array_available()); + Isolate* isolate = masm->isolate(); + ExternalReference limit = ExternalReference::address_of_real_jslimit(isolate); + DCHECK(TurboAssembler::IsAddressableThroughRootRegister(isolate, limit)); + + intptr_t offset = + TurboAssembler::RootRegisterOffsetForExternalReference(isolate, limit); + __ Lw(destination, MemOperand(kRootRegister, static_cast<int32_t>(offset))); +} + void Generate_JSBuiltinsConstructStubHelper(MacroAssembler* masm) { // ----------- S t a t e ------------- // -- a0 : number of arguments @@ -156,7 +167,7 @@ static void Generate_StackOverflowCheck(MacroAssembler* masm, Register num_args, // 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(scratch1, RootIndex::kRealStackLimit); + LoadRealStackLimit(masm, scratch1); // Make scratch1 the space we have left. The stack might already be overflowed // here which will cause scratch1 to become negative. __ subu(scratch1, sp, scratch1); @@ -368,7 +379,7 @@ static void Generate_CheckStackOverflow(MacroAssembler* masm, Register argc, // interruptions (e.g. debug break and preemption) here, so the "real stack // limit" is checked. Label okay; - __ LoadRoot(scratch1, RootIndex::kRealStackLimit); + LoadRealStackLimit(masm, scratch1); // Make a2 the space we have left. The stack might already be overflowed // here which will cause a2 to become negative. __ Subu(scratch1, sp, scratch1); @@ -715,7 +726,7 @@ void Builtins::Generate_ResumeGeneratorTrampoline(MacroAssembler* masm) { // Check the stack for overflow. We are not trying to catch interruptions // (i.e. debug break and preemption) here, so check the "real stack limit". Label stack_overflow; - __ LoadRoot(kScratchReg, RootIndex::kRealStackLimit); + LoadRealStackLimit(masm, kScratchReg); __ Branch(&stack_overflow, lo, sp, Operand(kScratchReg)); // Push receiver. @@ -1082,7 +1093,7 @@ void Builtins::Generate_InterpreterEntryTrampoline(MacroAssembler* masm) { // Do a stack check to ensure we don't go over the limit. Label ok; __ Subu(t1, sp, Operand(t0)); - __ LoadRoot(a2, RootIndex::kRealStackLimit); + LoadRealStackLimit(masm, a2); __ Branch(&ok, hs, t1, Operand(a2)); __ CallRuntime(Runtime::kThrowStackOverflow); __ bind(&ok); @@ -2061,7 +2072,7 @@ void Builtins::Generate_CallBoundFunctionImpl(MacroAssembler* masm) { __ Subu(sp, sp, Operand(t1)); // Check the stack for overflow. We are not trying to catch interruptions // (i.e. debug break and preemption) here, so check the "real stack limit". - __ LoadRoot(kScratchReg, RootIndex::kRealStackLimit); + LoadRealStackLimit(masm, kScratchReg); __ Branch(&done, hs, sp, Operand(kScratchReg)); // Restore the stack pointer. __ Addu(sp, sp, Operand(t1)); @@ -2219,7 +2230,7 @@ void Builtins::Generate_ConstructBoundFunction(MacroAssembler* masm) { __ Subu(sp, sp, Operand(t1)); // Check the stack for overflow. We are not trying to catch interruptions // (i.e. debug break and preemption) here, so check the "real stack limit". - __ LoadRoot(kScratchReg, RootIndex::kRealStackLimit); + LoadRealStackLimit(masm, kScratchReg); __ Branch(&done, hs, sp, Operand(kScratchReg)); // Restore the stack pointer. __ Addu(sp, sp, Operand(t1)); @@ -2488,7 +2499,10 @@ void Builtins::Generate_WasmCompileLazy(MacroAssembler* masm) { __ Push(kWasmInstanceRegister, kWasmCompileLazyFuncIndexRegister); // Load the correct CEntry builtin from the instance object. __ lw(a2, FieldMemOperand(kWasmInstanceRegister, - WasmInstanceObject::kCEntryStubOffset)); + WasmInstanceObject::kIsolateRootOffset)); + auto centry_id = + Builtins::kCEntry_Return1_DontSaveFPRegs_ArgvOnStack_NoBuiltinExit; + __ lw(a2, MemOperand(a2, IsolateData::builtin_slot_offset(centry_id))); // Initialize the JavaScript context with 0. CEntry will use it to // set the current context on the isolate. __ Move(kContextRegister, Smi::zero()); diff --git a/deps/v8/src/builtins/mips64/builtins-mips64.cc b/deps/v8/src/builtins/mips64/builtins-mips64.cc index c5565b90de..7cb66470a3 100644 --- a/deps/v8/src/builtins/mips64/builtins-mips64.cc +++ b/deps/v8/src/builtins/mips64/builtins-mips64.cc @@ -83,6 +83,18 @@ static void GenerateTailCallToReturnedCode(MacroAssembler* masm, namespace { +void LoadRealStackLimit(MacroAssembler* masm, Register destination) { + DCHECK(masm->root_array_available()); + Isolate* isolate = masm->isolate(); + ExternalReference limit = ExternalReference::address_of_real_jslimit(isolate); + DCHECK(TurboAssembler::IsAddressableThroughRootRegister(isolate, limit)); + + intptr_t offset = + TurboAssembler::RootRegisterOffsetForExternalReference(isolate, limit); + CHECK(is_int32(offset)); + __ Ld(destination, MemOperand(kRootRegister, static_cast<int32_t>(offset))); +} + void Generate_JSBuiltinsConstructStubHelper(MacroAssembler* masm) { // ----------- S t a t e ------------- // -- a0 : number of arguments @@ -156,7 +168,7 @@ static void Generate_StackOverflowCheck(MacroAssembler* masm, Register num_args, // 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(scratch1, RootIndex::kRealStackLimit); + LoadRealStackLimit(masm, scratch1); // Make scratch1 the space we have left. The stack might already be overflowed // here which will cause scratch1 to become negative. __ dsubu(scratch1, sp, scratch1); @@ -407,7 +419,7 @@ void Builtins::Generate_ResumeGeneratorTrampoline(MacroAssembler* masm) { // Check the stack for overflow. We are not trying to catch interruptions // (i.e. debug break and preemption) here, so check the "real stack limit". Label stack_overflow; - __ LoadRoot(kScratchReg, RootIndex::kRealStackLimit); + LoadRealStackLimit(masm, kScratchReg); __ Branch(&stack_overflow, lo, sp, Operand(kScratchReg)); // Push receiver. @@ -514,7 +526,7 @@ static void Generate_CheckStackOverflow(MacroAssembler* masm, Register argc, // interruptions (e.g. debug break and preemption) here, so the "real stack // limit" is checked. Label okay; - __ LoadRoot(scratch1, RootIndex::kRealStackLimit); + LoadRealStackLimit(masm, scratch1); // Make a2 the space we have left. The stack might already be overflowed // here which will cause r2 to become negative. __ dsubu(scratch1, sp, scratch1); @@ -1099,7 +1111,7 @@ void Builtins::Generate_InterpreterEntryTrampoline(MacroAssembler* masm) { // Do a stack check to ensure we don't go over the limit. Label ok; __ Dsubu(a5, sp, Operand(a4)); - __ LoadRoot(a2, RootIndex::kRealStackLimit); + LoadRealStackLimit(masm, a2); __ Branch(&ok, hs, a5, Operand(a2)); __ CallRuntime(Runtime::kThrowStackOverflow); __ bind(&ok); @@ -2100,7 +2112,7 @@ void Builtins::Generate_CallBoundFunctionImpl(MacroAssembler* masm) { __ Dsubu(sp, sp, Operand(a5)); // Check the stack for overflow. We are not trying to catch interruptions // (i.e. debug break and preemption) here, so check the "real stack limit". - __ LoadRoot(kScratchReg, RootIndex::kRealStackLimit); + LoadRealStackLimit(masm, kScratchReg); __ Branch(&done, hs, sp, Operand(kScratchReg)); // Restore the stack pointer. __ Daddu(sp, sp, Operand(a5)); @@ -2254,7 +2266,7 @@ void Builtins::Generate_ConstructBoundFunction(MacroAssembler* masm) { __ Dsubu(sp, sp, Operand(a5)); // Check the stack for overflow. We are not trying to catch interruptions // (i.e. debug break and preemption) here, so check the "real stack limit". - __ LoadRoot(kScratchReg, RootIndex::kRealStackLimit); + LoadRealStackLimit(masm, kScratchReg); __ Branch(&done, hs, sp, Operand(kScratchReg)); // Restore the stack pointer. __ Daddu(sp, sp, Operand(a5)); @@ -2525,7 +2537,10 @@ void Builtins::Generate_WasmCompileLazy(MacroAssembler* masm) { __ Push(kWasmInstanceRegister, kWasmCompileLazyFuncIndexRegister); // Load the correct CEntry builtin from the instance object. __ Ld(a2, FieldMemOperand(kWasmInstanceRegister, - WasmInstanceObject::kCEntryStubOffset)); + WasmInstanceObject::kIsolateRootOffset)); + auto centry_id = + Builtins::kCEntry_Return1_DontSaveFPRegs_ArgvOnStack_NoBuiltinExit; + __ Ld(a2, MemOperand(a2, IsolateData::builtin_slot_offset(centry_id))); // Initialize the JavaScript context with 0. CEntry will use it to // set the current context on the isolate. __ Move(kContextRegister, Smi::zero()); diff --git a/deps/v8/src/builtins/object-fromentries.tq b/deps/v8/src/builtins/object-fromentries.tq index 32115e78ea..fc36e34038 100644 --- a/deps/v8/src/builtins/object-fromentries.tq +++ b/deps/v8/src/builtins/object-fromentries.tq @@ -5,7 +5,7 @@ namespace object { transitioning macro ObjectFromEntriesFastCase(implicit context: Context)( - iterable: Object): JSObject labels IfSlow { + iterable: JSAny): JSObject labels IfSlow { typeswitch (iterable) { case (array: FastJSArrayWithNoCustomIteration): { const elements: FixedArray = @@ -14,7 +14,7 @@ namespace object { const result: JSObject = NewJSObject(); for (let k: Smi = 0; k < length; ++k) { - const value: Object = array::LoadElementOrUndefined(elements, k); + const value: JSAny = array::LoadElementOrUndefined(elements, k); const pair: KeyValuePair = collections::LoadKeyValuePairNoSideEffects(value) otherwise IfSlow; @@ -26,16 +26,16 @@ namespace object { } return result; } - case (Object): { + case (JSAny): { goto IfSlow; } } } transitioning javascript builtin - ObjectFromEntries(js-implicit context: Context, receiver: Object)( - ...arguments): Object { - const iterable: Object = arguments[0]; + ObjectFromEntries(js-implicit context: Context, receiver: JSAny)( + ...arguments): JSAny { + const iterable: JSAny = arguments[0]; try { if (IsNullOrUndefined(iterable)) goto Throw; return ObjectFromEntriesFastCase(iterable) otherwise IfSlow; @@ -50,7 +50,7 @@ namespace object { const step: JSReceiver = iterator::IteratorStep(i, fastIteratorResultMap) otherwise return result; - const iteratorValue: Object = + const iteratorValue: JSAny = iterator::IteratorValue(step, fastIteratorResultMap); const pair: KeyValuePair = collections::LoadKeyValuePair(iteratorValue); diff --git a/deps/v8/src/builtins/object.tq b/deps/v8/src/builtins/object.tq index 6706a8f943..3dc973cf40 100644 --- a/deps/v8/src/builtins/object.tq +++ b/deps/v8/src/builtins/object.tq @@ -4,31 +4,31 @@ namespace runtime { extern transitioning runtime - ObjectIsExtensible(implicit context: Context)(Object): Object; + ObjectIsExtensible(implicit context: Context)(JSAny): JSAny; extern transitioning runtime JSReceiverPreventExtensionsThrow(implicit context: Context)(JSReceiver): - Object; + JSAny; extern transitioning runtime JSReceiverPreventExtensionsDontThrow(implicit context: Context)(JSReceiver): - Object; + JSAny; extern transitioning runtime - JSReceiverGetPrototypeOf(implicit context: Context)(JSReceiver): Object; + JSReceiverGetPrototypeOf(implicit context: Context)(JSReceiver): JSAny; extern transitioning runtime - JSReceiverSetPrototypeOfThrow(implicit context: Context)(JSReceiver, Object): - Object; + JSReceiverSetPrototypeOfThrow(implicit context: Context)(JSReceiver, JSAny): + JSAny; extern transitioning runtime JSReceiverSetPrototypeOfDontThrow(implicit context: - Context)(JSReceiver, Object): Object; + Context)(JSReceiver, JSAny): JSAny; } // namespace runtime namespace object { transitioning macro - ObjectIsExtensible(implicit context: Context)(object: Object): Object { + ObjectIsExtensible(implicit context: Context)(object: JSAny): JSAny { const objectJSReceiver = Cast<JSReceiver>(object) otherwise return False; const objectJSProxy = Cast<JSProxy>(objectJSReceiver) otherwise return runtime::ObjectIsExtensible(objectJSReceiver); @@ -36,8 +36,8 @@ namespace object { } transitioning macro - ObjectPreventExtensionsThrow(implicit context: Context)(object: Object): - Object { + ObjectPreventExtensionsThrow(implicit context: Context)(object: JSAny): + JSAny { const objectJSReceiver = Cast<JSReceiver>(object) otherwise return object; const objectJSProxy = Cast<JSProxy>(objectJSReceiver) otherwise return runtime::JSReceiverPreventExtensionsThrow( @@ -47,8 +47,8 @@ namespace object { } transitioning macro - ObjectPreventExtensionsDontThrow(implicit context: Context)(object: Object): - Object { + ObjectPreventExtensionsDontThrow(implicit context: Context)(object: JSAny): + JSAny { const objectJSReceiver = Cast<JSReceiver>(object) otherwise return False; const objectJSProxy = Cast<JSProxy>(objectJSReceiver) otherwise return runtime::JSReceiverPreventExtensionsDontThrow( @@ -57,14 +57,14 @@ namespace object { } transitioning macro - ObjectGetPrototypeOf(implicit context: Context)(object: Object): Object { + ObjectGetPrototypeOf(implicit context: Context)(object: JSAny): JSAny { const objectJSReceiver: JSReceiver = ToObject_Inline(context, object); return object::JSReceiverGetPrototypeOf(objectJSReceiver); } transitioning macro JSReceiverGetPrototypeOf(implicit context: Context)(object: JSReceiver): - Object { + JSAny { const objectJSProxy = Cast<JSProxy>(object) otherwise return runtime::JSReceiverGetPrototypeOf(object); return proxy::ProxyGetPrototypeOf(objectJSProxy); @@ -72,7 +72,7 @@ namespace object { transitioning macro ObjectSetPrototypeOfThrow(implicit context: Context)( - object: Object, proto: Object): Object { + object: JSAny, proto: JSReceiver | Null): JSAny { const objectJSReceiver = Cast<JSReceiver>(object) otherwise return object; const objectJSProxy = Cast<JSProxy>(objectJSReceiver) otherwise return runtime::JSReceiverSetPrototypeOfThrow( @@ -83,7 +83,7 @@ namespace object { transitioning macro ObjectSetPrototypeOfDontThrow(implicit context: Context)( - object: Object, proto: Object): Object { + object: JSAny, proto: JSReceiver | Null): JSAny { const objectJSReceiver = Cast<JSReceiver>(object) otherwise return False; const objectJSProxy = Cast<JSProxy>(objectJSReceiver) otherwise return runtime::JSReceiverSetPrototypeOfDontThrow( @@ -94,24 +94,24 @@ namespace object { namespace object_isextensible { // ES6 section 19.1.2.11 Object.isExtensible ( O ) - transitioning javascript builtin ObjectIsExtensible( - js-implicit context: Context)(_receiver: Object, object: Object): Object { + transitioning javascript builtin + ObjectIsExtensible(js-implicit context: Context)(object: JSAny): JSAny { return object::ObjectIsExtensible(object); } } // namespace object_isextensible namespace object_preventextensions { // ES6 section 19.1.2.11 Object.isExtensible ( O ) - transitioning javascript builtin ObjectPreventExtensions( - js-implicit context: Context)(_receiver: Object, object: Object): Object { + transitioning javascript builtin + ObjectPreventExtensions(js-implicit context: Context)(object: JSAny): JSAny { return object::ObjectPreventExtensionsThrow(object); } } // namespace object_preventextensions namespace object_getprototypeof { // ES6 section 19.1.2.9 Object.getPrototypeOf ( O ) - transitioning javascript builtin ObjectGetPrototypeOf( - js-implicit context: Context)(_receiver: Object, object: Object): Object { + transitioning javascript builtin + ObjectGetPrototypeOf(js-implicit context: Context)(object: JSAny): JSAny { return object::ObjectGetPrototypeOf(object); } } // namespace object_getprototypeof @@ -119,8 +119,7 @@ namespace object_getprototypeof { namespace object_setprototypeof { // ES6 section 19.1.2.21 Object.setPrototypeOf ( O, proto ) transitioning javascript builtin ObjectSetPrototypeOf( - js-implicit context: - Context)(_receiver: Object, object: Object, proto: Object): Object { + js-implicit context: Context)(object: JSAny, proto: JSAny): JSAny { // 1. Set O to ? RequireObjectCoercible(O). RequireObjectCoercible(object, 'Object.setPrototypeOf'); @@ -130,9 +129,13 @@ namespace object_setprototypeof { // 4. Let status be ? O.[[SetPrototypeOf]](proto). // 5. If status is false, throw a TypeError exception. // 6. Return O. - if (proto == Null || Is<JSReceiver>(proto)) { - return object::ObjectSetPrototypeOfThrow(object, proto); + typeswitch (proto) { + case (proto: JSReceiver | Null): { + return object::ObjectSetPrototypeOfThrow(object, proto); + } + case (JSAny): { + ThrowTypeError(kProtoObjectOrNull, proto); + } } - ThrowTypeError(kProtoObjectOrNull, proto); } } // namespace object_setprototypeof diff --git a/deps/v8/src/builtins/ppc/builtins-ppc.cc b/deps/v8/src/builtins/ppc/builtins-ppc.cc index a42cb9bebd..485b793395 100644 --- a/deps/v8/src/builtins/ppc/builtins-ppc.cc +++ b/deps/v8/src/builtins/ppc/builtins-ppc.cc @@ -81,12 +81,24 @@ static void GenerateTailCallToReturnedCode(MacroAssembler* masm, namespace { +void LoadRealStackLimit(MacroAssembler* masm, Register destination) { + DCHECK(masm->root_array_available()); + Isolate* isolate = masm->isolate(); + ExternalReference limit = ExternalReference::address_of_real_jslimit(isolate); + DCHECK(TurboAssembler::IsAddressableThroughRootRegister(isolate, limit)); + + intptr_t offset = + TurboAssembler::RootRegisterOffsetForExternalReference(isolate, limit); + CHECK(is_int32(offset)); + __ LoadP(destination, MemOperand(kRootRegister, offset)); +} + 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); + LoadRealStackLimit(masm, scratch); // 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); @@ -437,7 +449,8 @@ void Builtins::Generate_ResumeGeneratorTrampoline(MacroAssembler* masm) { // Check the stack for overflow. We are not trying to catch interruptions // (i.e. debug break and preemption) here, so check the "real stack limit". Label stack_overflow; - __ CompareRoot(sp, RootIndex::kRealStackLimit); + LoadRealStackLimit(masm, scratch); + __ cmpl(sp, scratch); __ blt(&stack_overflow); // Push receiver. @@ -729,7 +742,7 @@ static void Generate_CheckStackOverflow(MacroAssembler* masm, Register argc, // interruptions (e.g. debug break and preemption) here, so the "real stack // limit" is checked. Label okay; - __ LoadRoot(scratch1, RootIndex::kRealStackLimit); + LoadRealStackLimit(masm, scratch1); // Make scratch1 the space we have left. The stack might already be overflowed // here which will cause scratch1 to become negative. __ sub(scratch1, sp, scratch1); @@ -1144,7 +1157,7 @@ void Builtins::Generate_InterpreterEntryTrampoline(MacroAssembler* masm) { // Do a stack check to ensure we don't go over the limit. Label ok; __ sub(r8, sp, r5); - __ LoadRoot(r0, RootIndex::kRealStackLimit); + LoadRealStackLimit(masm, r0); __ cmpl(r8, r0); __ bge(&ok); __ CallRuntime(Runtime::kThrowStackOverflow); @@ -2163,7 +2176,12 @@ void Generate_PushBoundArguments(MacroAssembler* masm) { // Check the stack for overflow. We are not trying to catch interruptions // (i.e. debug break and preemption) here, so check the "real stack // limit". - __ CompareRoot(sp, RootIndex::kRealStackLimit); + { + UseScratchRegisterScope temps(masm); + Register scratch = temps.Acquire(); + LoadRealStackLimit(masm, scratch); + __ cmpl(sp, scratch); + } __ bgt(&done); // Signed comparison. // Restore the stack pointer. __ mr(sp, scratch); @@ -2599,7 +2617,10 @@ void Builtins::Generate_WasmCompileLazy(MacroAssembler* masm) { __ Push(kWasmInstanceRegister, kWasmCompileLazyFuncIndexRegister); // Load the correct CEntry builtin from the instance object. __ LoadP(r5, FieldMemOperand(kWasmInstanceRegister, - WasmInstanceObject::kCEntryStubOffset)); + WasmInstanceObject::kIsolateRootOffset)); + auto centry_id = + Builtins::kCEntry_Return1_DontSaveFPRegs_ArgvOnStack_NoBuiltinExit; + __ LoadP(r5, MemOperand(r5, IsolateData::builtin_slot_offset(centry_id))); // Initialize the JavaScript context with 0. CEntry will use it to // set the current context on the isolate. __ LoadSmiLiteral(cp, Smi::zero()); diff --git a/deps/v8/src/builtins/proxy-constructor.tq b/deps/v8/src/builtins/proxy-constructor.tq index ad60c20e2c..cfb11046a7 100644 --- a/deps/v8/src/builtins/proxy-constructor.tq +++ b/deps/v8/src/builtins/proxy-constructor.tq @@ -10,8 +10,8 @@ namespace proxy { // https://tc39.github.io/ecma262/#sec-proxy-constructor transitioning javascript builtin ProxyConstructor( - js-implicit context: Context, receiver: Object, - newTarget: Object)(target: Object, handler: Object): JSProxy { + js-implicit context: Context, receiver: JSAny, + newTarget: JSAny)(target: JSAny, handler: JSAny): JSProxy { try { // 1. If NewTarget is undefined, throw a TypeError exception. if (newTarget == Undefined) { diff --git a/deps/v8/src/builtins/proxy-delete-property.tq b/deps/v8/src/builtins/proxy-delete-property.tq index 759de766ef..3054c0d07a 100644 --- a/deps/v8/src/builtins/proxy-delete-property.tq +++ b/deps/v8/src/builtins/proxy-delete-property.tq @@ -10,8 +10,10 @@ namespace proxy { // https://tc39.es/ecma262/#sec-proxy-object-internal-methods-and-internal-slots-delete-p transitioning builtin ProxyDeleteProperty(implicit context: Context)( - proxy: JSProxy, name: Name, languageMode: LanguageMode): Object { + proxy: JSProxy, name: PropertyKey, languageMode: LanguageMode): JSAny { const kTrapName: constexpr string = 'deleteProperty'; + // Handle deeply nested proxy. + PerformStackCheck(); // 1. Assert: IsPropertyKey(P) is true. assert(TaggedIsNotSmi(name)); assert(IsName(name)); @@ -38,7 +40,7 @@ namespace proxy { const trapResult = Call(context, trap, handler, target, name); // 9. If booleanTrapResult is false, return false. - if (BranchIfToBooleanIsFalse(trapResult)) { + if (!ToBoolean(trapResult)) { if (languageMode == SmiConstant(kStrict)) { ThrowTypeError(kProxyTrapReturnedFalsishFor, kTrapName, name); } @@ -56,7 +58,7 @@ namespace proxy { // 15. Return true. return True; } - label TrapUndefined(target: Object) { + label TrapUndefined(target: JSAny) { // 7.a. Return ? target.[[Delete]](P). return DeleteProperty(target, name, languageMode); } diff --git a/deps/v8/src/builtins/proxy-get-property.tq b/deps/v8/src/builtins/proxy-get-property.tq index bac07f550c..54b8cde243 100644 --- a/deps/v8/src/builtins/proxy-get-property.tq +++ b/deps/v8/src/builtins/proxy-get-property.tq @@ -7,14 +7,14 @@ namespace proxy { extern transitioning builtin GetPropertyWithReceiver( - implicit context: Context)(Object, Name, Object, Smi): Object; + implicit context: Context)(JSAny, Name, JSAny, Smi): JSAny; // ES #sec-proxy-object-internal-methods-and-internal-slots-get-p-receiver // https://tc39.github.io/ecma262/#sec-proxy-object-internal-methods-and-internal-slots-get-p-receiver transitioning builtin ProxyGetProperty(implicit context: Context)( - proxy: JSProxy, name: Name, receiverValue: Object, - onNonExistent: Smi): Object { + proxy: JSProxy, name: PropertyKey, receiverValue: JSAny, + onNonExistent: Smi): JSAny { PerformStackCheck(); // 1. Assert: IsPropertyKey(P) is true. assert(TaggedIsNotSmi(name)); diff --git a/deps/v8/src/builtins/proxy-get-prototype-of.tq b/deps/v8/src/builtins/proxy-get-prototype-of.tq index 2418eaf423..653d4503d1 100644 --- a/deps/v8/src/builtins/proxy-get-prototype-of.tq +++ b/deps/v8/src/builtins/proxy-get-prototype-of.tq @@ -9,7 +9,7 @@ namespace proxy { // ES #sec-proxy-object-internal-methods-and-internal-slots-isextensible // https://tc39.github.io/ecma262/#sec-proxy-object-internal-methods-and-internal-slots-isextensible transitioning builtin - ProxyGetPrototypeOf(implicit context: Context)(proxy: JSProxy): Object { + ProxyGetPrototypeOf(implicit context: Context)(proxy: JSProxy): JSAny { PerformStackCheck(); const kTrapName: constexpr string = 'getPrototypeOf'; try { @@ -39,7 +39,7 @@ namespace proxy { // 9. Let extensibleTarget be ? IsExtensible(target). // 10. If extensibleTarget is true, return handlerProto. - const extensibleTarget: Object = object::ObjectIsExtensible(target); + const extensibleTarget: JSAny = object::ObjectIsExtensible(target); assert(extensibleTarget == True || extensibleTarget == False); if (extensibleTarget == True) { return handlerProto; @@ -51,12 +51,12 @@ namespace proxy { // 12. If SameValue(handlerProto, targetProto) is false, throw a TypeError // exception. // 13. Return handlerProto. - if (BranchIfSameValue(targetProto, handlerProto)) { + if (SameValue(targetProto, handlerProto)) { return handlerProto; } ThrowTypeError(kProxyGetPrototypeOfNonExtensible); } - label TrapUndefined(target: Object) { + label TrapUndefined(target: JSAny) { // 6.a. Return ? target.[[GetPrototypeOf]](). return object::ObjectGetPrototypeOf(target); } diff --git a/deps/v8/src/builtins/proxy-has-property.tq b/deps/v8/src/builtins/proxy-has-property.tq index ee394c5d84..1f14c68903 100644 --- a/deps/v8/src/builtins/proxy-has-property.tq +++ b/deps/v8/src/builtins/proxy-has-property.tq @@ -9,7 +9,7 @@ namespace proxy { // ES #sec-proxy-object-internal-methods-and-internal-slots-hasproperty-p // https://tc39.github.io/ecma262/#sec-proxy-object-internal-methods-and-internal-slots-hasproperty-p transitioning builtin ProxyHasProperty(implicit context: Context)( - proxy: JSProxy, name: Name): Object { + proxy: JSProxy, name: PropertyKey): JSAny { assert(IsJSProxy(proxy)); PerformStackCheck(); @@ -40,13 +40,13 @@ namespace proxy { // CheckHasTrapResult). // 10. Return booleanTrapResult. const trapResult = Call(context, trap, handler, target, name); - if (BranchIfToBooleanIsTrue(trapResult)) { + if (ToBoolean(trapResult)) { return True; } CheckHasTrapResult(target, proxy, name); return False; } - label TrapUndefined(target: Object) { + label TrapUndefined(target: JSAny) { // 7.a. Return ? target.[[HasProperty]](P). tail HasProperty(target, name); } diff --git a/deps/v8/src/builtins/proxy-is-extensible.tq b/deps/v8/src/builtins/proxy-is-extensible.tq index 82f4a5b955..dfbdc6f734 100644 --- a/deps/v8/src/builtins/proxy-is-extensible.tq +++ b/deps/v8/src/builtins/proxy-is-extensible.tq @@ -9,7 +9,7 @@ namespace proxy { // ES #sec-proxy-object-internal-methods-and-internal-slots-isextensible // https://tc39.github.io/ecma262/#sec-proxy-object-internal-methods-and-internal-slots-isextensible transitioning builtin ProxyIsExtensible(implicit context: - Context)(proxy: JSProxy): Object { + Context)(proxy: JSProxy): JSAny { PerformStackCheck(); const kTrapName: constexpr string = 'isExtensible'; try { @@ -45,7 +45,7 @@ namespace proxy { // 10. Return booleanTrapResult. return SelectBooleanConstant(trapResult); } - label TrapUndefined(target: Object) { + label TrapUndefined(target: JSAny) { // 6.a. Return ? IsExtensible(target). return object::ObjectIsExtensible(target); } diff --git a/deps/v8/src/builtins/proxy-prevent-extensions.tq b/deps/v8/src/builtins/proxy-prevent-extensions.tq index 6d5d2569fb..ab75cfc4cb 100644 --- a/deps/v8/src/builtins/proxy-prevent-extensions.tq +++ b/deps/v8/src/builtins/proxy-prevent-extensions.tq @@ -9,8 +9,8 @@ namespace proxy { // ES #sec-proxy-object-internal-methods-and-internal-slots-preventextensions // https://tc39.es/ecma262/#sec-proxy-object-internal-methods-and-internal-slots-preventextensions transitioning builtin - ProxyPreventExtensions(implicit context: Context)( - proxy: JSProxy, doThrow: Boolean): Object { + ProxyPreventExtensions(implicit context: + Context)(proxy: JSProxy, doThrow: Boolean): JSAny { PerformStackCheck(); const kTrapName: constexpr string = 'preventExtensions'; try { @@ -36,8 +36,8 @@ namespace proxy { // 8. If booleanTrapResult is true, then // 8.a. Let extensibleTarget be ? IsExtensible(target). // 8.b If extensibleTarget is true, throw a TypeError exception. - if (BranchIfToBooleanIsTrue(trapResult)) { - const extensibleTarget: Object = object::ObjectIsExtensible(target); + if (ToBoolean(trapResult)) { + const extensibleTarget: JSAny = object::ObjectIsExtensible(target); assert(extensibleTarget == True || extensibleTarget == False); if (extensibleTarget == True) { ThrowTypeError(kProxyPreventExtensionsExtensible); @@ -52,7 +52,7 @@ namespace proxy { // 9. Return booleanTrapResult. return True; } - label TrapUndefined(target: Object) { + label TrapUndefined(target: JSAny) { // 6.a. Return ? target.[[PreventExtensions]](). if (doThrow == True) { return object::ObjectPreventExtensionsThrow(target); diff --git a/deps/v8/src/builtins/proxy-revocable.tq b/deps/v8/src/builtins/proxy-revocable.tq index b09baab9cf..465b1aef96 100644 --- a/deps/v8/src/builtins/proxy-revocable.tq +++ b/deps/v8/src/builtins/proxy-revocable.tq @@ -12,9 +12,8 @@ namespace proxy { // 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 { + ProxyRevocable(js-implicit context: Context)(target: JSAny, handler: JSAny): + JSProxyRevocableResult { try { const targetJSReceiver = Cast<JSReceiver>(target) otherwise ThrowProxyNonObject; diff --git a/deps/v8/src/builtins/proxy-set-property.tq b/deps/v8/src/builtins/proxy-set-property.tq index d0411a8e89..2d9636c881 100644 --- a/deps/v8/src/builtins/proxy-set-property.tq +++ b/deps/v8/src/builtins/proxy-set-property.tq @@ -19,15 +19,21 @@ namespace proxy { // https://tc39.github.io/ecma262/#sec-proxy-object-internal-methods-and-internal-slots-set-p-v-receiver transitioning builtin ProxySetProperty(implicit context: Context)( - proxy: JSProxy, name: Name, value: Object, - receiverValue: Object): Object { + proxy: JSProxy, name: PropertyKey | PrivateSymbol, value: JSAny, + receiverValue: JSAny): JSAny { // 1. Assert: IsPropertyKey(P) is true. assert(TaggedIsNotSmi(name)); assert(IsName(name)); - if (IsPrivateSymbol(name)) { - CallThrowTypeErrorIfStrict(kProxyPrivate); - return Undefined; + let key: PropertyKey; + typeswitch (name) { + case (PrivateSymbol): { + CallThrowTypeErrorIfStrict(kProxyPrivate); + return Undefined; + } + case (name: PropertyKey): { + key = name; + } } try { @@ -61,8 +67,8 @@ namespace proxy { // exception. // 12. Return true. const trapResult = - Call(context, trap, handler, target, name, value, receiverValue); - if (BranchIfToBooleanIsTrue(trapResult)) { + Call(context, trap, handler, target, key, value, receiverValue); + if (ToBoolean(trapResult)) { CheckGetSetTrapResult(target, proxy, name, value, kProxySet); return value; } diff --git a/deps/v8/src/builtins/proxy-set-prototype-of.tq b/deps/v8/src/builtins/proxy-set-prototype-of.tq index bbd99be411..355c258ab8 100644 --- a/deps/v8/src/builtins/proxy-set-prototype-of.tq +++ b/deps/v8/src/builtins/proxy-set-prototype-of.tq @@ -10,7 +10,7 @@ namespace proxy { // https://tc39.es/ecma262/#sec-proxy-object-internal-methods-and-internal-slots-setprototypeof-v transitioning builtin ProxySetPrototypeOf(implicit context: Context)( - proxy: JSProxy, proto: Object, doThrow: Boolean): Object { + proxy: JSProxy, proto: Null | JSReceiver, doThrow: Boolean): JSAny { PerformStackCheck(); const kTrapName: constexpr string = 'setPrototypeOf'; try { @@ -37,7 +37,7 @@ namespace proxy { const trapResult = Call(context, trap, handler, target, proto); // 9. If booleanTrapResult is false, return false. - if (BranchIfToBooleanIsFalse(trapResult)) { + if (!ToBoolean(trapResult)) { if (doThrow == True) { ThrowTypeError(kProxyTrapReturnedFalsishFor, kTrapName); } @@ -58,12 +58,12 @@ namespace proxy { // 13. If SameValue(V, targetProto) is false, throw a TypeError // exception. // 14. Return true. - if (BranchIfSameValue(proto, targetProto)) { + if (SameValue(proto, targetProto)) { return True; } ThrowTypeError(kProxySetPrototypeOfNonExtensible); } - label TrapUndefined(target: Object, proto: Object) { + label TrapUndefined(target: JSAny, proto: JSReceiver | Null) { // 7.a. Return ? target.[[SetPrototypeOf]](). if (doThrow == True) { return object::ObjectSetPrototypeOfThrow(target, proto); diff --git a/deps/v8/src/builtins/reflect.tq b/deps/v8/src/builtins/reflect.tq index 4c25e8338f..97c6ec81a7 100644 --- a/deps/v8/src/builtins/reflect.tq +++ b/deps/v8/src/builtins/reflect.tq @@ -8,24 +8,24 @@ namespace reflect { generates 'MessageTemplate::kCalledOnNonObject'; // ES6 section 26.1.10 Reflect.isExtensible - transitioning javascript builtin ReflectIsExtensible( - js-implicit context: Context)(_receiver: Object, object: Object): Object { + transitioning javascript builtin + ReflectIsExtensible(js-implicit context: Context)(object: JSAny): JSAny { const objectJSReceiver = Cast<JSReceiver>(object) otherwise ThrowTypeError(kCalledOnNonObject, 'Reflect.isExtensible'); return object::ObjectIsExtensible(objectJSReceiver); } // ES6 section 26.1.12 Reflect.preventExtensions - transitioning javascript builtin ReflectPreventExtensions( - js-implicit context: Context)(_receiver: Object, object: Object): Object { + transitioning javascript builtin + ReflectPreventExtensions(js-implicit context: Context)(object: JSAny): JSAny { const objectJSReceiver = Cast<JSReceiver>(object) otherwise ThrowTypeError(kCalledOnNonObject, 'Reflect.preventExtensions'); return object::ObjectPreventExtensionsDontThrow(objectJSReceiver); } // ES6 section 26.1.8 Reflect.getPrototypeOf - transitioning javascript builtin ReflectGetPrototypeOf( - js-implicit context: Context)(_receiver: Object, object: Object): Object { + transitioning javascript builtin + ReflectGetPrototypeOf(js-implicit context: Context)(object: JSAny): JSAny { const objectJSReceiver = Cast<JSReceiver>(object) otherwise ThrowTypeError(kCalledOnNonObject, 'Reflect.getPrototypeOf'); return object::JSReceiverGetPrototypeOf(objectJSReceiver); @@ -33,50 +33,47 @@ namespace reflect { // ES6 section 26.1.14 Reflect.setPrototypeOf transitioning javascript builtin ReflectSetPrototypeOf( - js-implicit context: - Context)(_receiver: Object, object: Object, proto: Object): Object { + js-implicit context: Context)(object: JSAny, proto: JSAny): JSAny { const objectJSReceiver = Cast<JSReceiver>(object) otherwise ThrowTypeError(kCalledOnNonObject, 'Reflect.setPrototypeOf'); - if (proto == Null || Is<JSReceiver>(proto)) { - return object::ObjectSetPrototypeOfDontThrow(objectJSReceiver, proto); + typeswitch (proto) { + case (proto: JSReceiver | Null): { + return object::ObjectSetPrototypeOfDontThrow(objectJSReceiver, proto); + } + case (JSAny): { + ThrowTypeError(kProtoObjectOrNull, proto); + } } - ThrowTypeError(kProtoObjectOrNull, proto); } - extern transitioning builtin ToName(implicit context: Context)(Object): Name; + extern transitioning builtin ToName(implicit context: Context)(JSAny): + AnyName; type OnNonExistent constexpr 'OnNonExistent'; const kReturnUndefined: constexpr OnNonExistent generates 'OnNonExistent::kReturnUndefined'; extern macro SmiConstant(constexpr OnNonExistent): Smi; extern transitioning builtin GetPropertyWithReceiver( - implicit context: Context)(Object, Name, Object, Smi): Object; + implicit context: Context)(JSAny, Name, JSAny, Smi): JSAny; // ES6 section 26.1.6 Reflect.get transitioning javascript builtin - ReflectGet(js-implicit context: Context)(...arguments): Object { + ReflectGet(js-implicit context: Context)(...arguments): JSAny { const length = arguments.length; - const object: Object = length > 0 ? arguments[0] : Undefined; + const object: JSAny = length > 0 ? arguments[0] : Undefined; const objectJSReceiver = Cast<JSReceiver>(object) otherwise ThrowTypeError(kCalledOnNonObject, 'Reflect.get'); - const propertyKey: Object = length > 1 ? arguments[1] : Undefined; - const name: Name = ToName(propertyKey); - const receiver: Object = length > 2 ? arguments[2] : objectJSReceiver; + const propertyKey: JSAny = length > 1 ? arguments[1] : Undefined; + const name: AnyName = ToName(propertyKey); + const receiver: JSAny = length > 2 ? arguments[2] : objectJSReceiver; return GetPropertyWithReceiver( objectJSReceiver, name, receiver, SmiConstant(kReturnUndefined)); } // ES6 section 26.1.4 Reflect.deleteProperty transitioning javascript builtin ReflectDeleteProperty( - js-implicit context: - Context)(_receiver: Object, object: Object, key: Object): Object { + js-implicit context: Context)(object: JSAny, key: JSAny): JSAny { const objectJSReceiver = Cast<JSReceiver>(object) otherwise ThrowTypeError(kCalledOnNonObject, 'Reflect.deleteProperty'); - const name: Name = ToName(key); - if (IsPrivateSymbol(name)) { - return DeleteProperty(objectJSReceiver, name, kSloppy); - } - const proxy = Cast<JSProxy>(objectJSReceiver) - otherwise return DeleteProperty(objectJSReceiver, name, kSloppy); - return proxy::ProxyDeleteProperty(proxy, name, kSloppy); + return DeleteProperty(objectJSReceiver, key, kSloppy); } } // namespace reflect diff --git a/deps/v8/src/builtins/regexp-match.tq b/deps/v8/src/builtins/regexp-match.tq new file mode 100644 index 0000000000..dbee8a616a --- /dev/null +++ b/deps/v8/src/builtins/regexp-match.tq @@ -0,0 +1,49 @@ +// 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 transitioning macro RegExpBuiltinsAssembler::RegExpPrototypeMatchBody( + implicit context: Context)(Object, String, constexpr bool): JSAny; + + transitioning macro FastRegExpPrototypeMatchBody(implicit context: Context)( + receiver: FastJSRegExp, string: String): JSAny { + return RegExpPrototypeMatchBody(receiver, string, true); + } + + transitioning macro SlowRegExpPrototypeMatchBody(implicit context: Context)( + receiver: Object, string: String): JSAny { + return RegExpPrototypeMatchBody(receiver, string, false); + } + + // Helper that skips a few initial checks. and assumes... + // 1) receiver is a "fast" RegExp + // 2) pattern is a string + transitioning builtin RegExpMatchFast(implicit context: Context)( + receiver: FastJSRegExp, string: String): JSAny { + return FastRegExpPrototypeMatchBody(receiver, string); + } + + // ES#sec-regexp.prototype-@@match + // RegExp.prototype [ @@match ] ( string ) + transitioning javascript builtin RegExpPrototypeMatch( + js-implicit context: Context, receiver: JSAny)(string: JSAny): JSAny { + ThrowIfNotJSReceiver( + receiver, kIncompatibleMethodReceiver, 'RegExp.prototype.@@match'); + const receiver = UnsafeCast<JSReceiver>(receiver); + const string: String = ToString_Inline(context, string); + + // Strict: Reads global and unicode properties. + // TODO(jgruber): Handle slow flag accesses on the fast path and make this + // permissive. + const fastRegExp = Cast<FastJSRegExp>(receiver) + otherwise return SlowRegExpPrototypeMatchBody(receiver, string); + + // TODO(pwong): Could be optimized to remove the overhead of calling the + // builtin (at the cost of a larger builtin). + return RegExpMatchFast(fastRegExp, string); + } +} diff --git a/deps/v8/src/builtins/regexp-replace.tq b/deps/v8/src/builtins/regexp-replace.tq index cb0038c6b6..f13724b476 100644 --- a/deps/v8/src/builtins/regexp-replace.tq +++ b/deps/v8/src/builtins/regexp-replace.tq @@ -4,7 +4,7 @@ #include 'src/builtins/builtins-regexp-gen.h' -namespace regexp_replace { +namespace regexp { extern builtin StringIndexOf(implicit context: Context)(String, String, Smi): Smi; @@ -23,10 +23,6 @@ namespace regexp_replace { extern macro RegExpBuiltinsAssembler::AdvanceStringIndexFast(String, Smi, bool): Smi; - extern macro - RegExpBuiltinsAssembler::RegExpPrototypeExecBodyWithoutResultFast( - implicit context: Context)(JSReceiver, String): - RegExpMatchInfo labels IfDidNotMatch; transitioning macro RegExpReplaceCallableNoExplicitCaptures(implicit context: Context)( @@ -57,7 +53,7 @@ namespace regexp_replace { // Element represents the matched substring, which is then passed to the // replace function. case (elString: String): { - const replacementObj: Object = + const replacementObj: JSAny = Call(context, replaceFn, Undefined, elString, matchStart, string); const replacement: String = ToString_Inline(context, replacementObj); matchesElements.objects[i] = replacement; @@ -79,7 +75,7 @@ namespace regexp_replace { // The JSArray is expanded into the function args by Reflect.apply(). // TODO(jgruber): Remove indirection through Call->ReflectApply. - const replacementObj: Object = Call( + const replacementObj: JSAny = Call( context, GetReflectApply(), Undefined, replaceFn, Undefined, elArray); // Overwrite the i'th element in the results with the string @@ -146,8 +142,9 @@ namespace regexp_replace { } while (true) { - const match: RegExpMatchInfo = RegExpPrototypeExecBodyWithoutResultFast( - regexp, string) otherwise break; + const match: RegExpMatchInfo = + regexp::RegExpPrototypeExecBodyWithoutResultFast(regexp, string) + otherwise break; const matchStart: Smi = match.GetStartOfCapture(0); const matchEnd: Smi = match.GetEndOfCapture(0); @@ -172,7 +169,7 @@ namespace regexp_replace { } transitioning builtin RegExpReplace(implicit context: Context)( - regexp: FastJSRegExp, string: String, replaceValue: Object): String { + regexp: FastJSRegExp, string: String, replaceValue: JSAny): String { // TODO(pwong): Remove assert when all callers (StringPrototypeReplace) are // from Torque. assert(Is<FastJSRegExp>(regexp)); @@ -184,7 +181,7 @@ namespace regexp_replace { RegExpReplaceFastGlobalCallable(regexp, string, replaceFn) : StringReplaceNonGlobalRegExpWithFunction(string, regexp, replaceFn); } - case (Object): { + case (JSAny): { const stableRegexp: JSRegExp = regexp; const replaceString: String = ToString_Inline(context, replaceValue); @@ -208,7 +205,7 @@ namespace regexp_replace { } transitioning javascript builtin RegExpPrototypeReplace( - js-implicit context: Context, receiver: Object)(...arguments): Object { + js-implicit context: Context, receiver: JSAny)(...arguments): JSAny { const methodName: constexpr string = 'RegExp.prototype.@@replace'; // RegExpPrototypeReplace is a bit of a beast - a summary of dispatch logic: @@ -229,8 +226,8 @@ namespace regexp_replace { // } // } - const string: Object = arguments[0]; - const replaceValue: Object = arguments[1]; + const string: JSAny = arguments[0]; + const replaceValue: JSAny = arguments[1]; // Let rx be the this value. // If Type(rx) is not Object, throw a TypeError exception. diff --git a/deps/v8/src/builtins/regexp-source.tq b/deps/v8/src/builtins/regexp-source.tq new file mode 100644 index 0000000000..c1ce1c5e9a --- /dev/null +++ b/deps/v8/src/builtins/regexp-source.tq @@ -0,0 +1,30 @@ +// 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 { + + const kRegExpPrototypeSourceGetter: constexpr int31 + generates 'v8::Isolate::kRegExpPrototypeSourceGetter'; + + // ES6 21.2.5.10. + // ES #sec-get-regexp.prototype.source + transitioning javascript builtin RegExpPrototypeSourceGetter( + js-implicit context: Context, receiver: JSAny)(): JSAny { + typeswitch (receiver) { + case (receiver: JSRegExp): { + return receiver.source; + } + case (Object): { + } + } + if (!IsReceiverInitialRegExpPrototype(receiver)) { + const methodName: constexpr string = 'RegExp.prototype.source'; + ThrowTypeError(kRegExpNonRegExp, methodName); + } + IncrementUseCounter(context, SmiConstant(kRegExpPrototypeSourceGetter)); + return '(?:)'; + } +} diff --git a/deps/v8/src/builtins/regexp-test.tq b/deps/v8/src/builtins/regexp-test.tq new file mode 100644 index 0000000000..938dfa51f3 --- /dev/null +++ b/deps/v8/src/builtins/regexp-test.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-regexp-gen.h' + +namespace regexp { + + // ES#sec-regexp.prototype.test + // RegExp.prototype.test ( S ) + transitioning javascript builtin RegExpPrototypeTest( + js-implicit context: Context, receiver: JSAny)(string: JSAny): JSAny { + const methodName: constexpr string = 'RegExp.prototype.test'; + const receiver = Cast<JSReceiver>(receiver) + otherwise ThrowTypeError(kIncompatibleMethodReceiver, methodName); + const str: String = ToString_Inline(context, string); + if (IsFastRegExpPermissive(receiver)) { + RegExpPrototypeExecBodyWithoutResultFast( + UnsafeCast<JSRegExp>(receiver), str) + otherwise return False; + return True; + } + const matchIndices = RegExpExec(context, receiver, str); + return SelectBooleanConstant(matchIndices != Null); + } + + extern macro RegExpBuiltinsAssembler::IsFastRegExpWithOriginalExec( + implicit context: Context)(JSRegExp): bool; + + transitioning builtin RegExpPrototypeTestFast(implicit context: Context)( + receiver: JSRegExp, string: String): Object { + assert(IsFastRegExpWithOriginalExec(receiver)); + RegExpPrototypeExecBodyWithoutResultFast(receiver, string) + otherwise return False; + return True; + } +} diff --git a/deps/v8/src/builtins/regexp.tq b/deps/v8/src/builtins/regexp.tq index a36e1a14eb..7352d2738f 100644 --- a/deps/v8/src/builtins/regexp.tq +++ b/deps/v8/src/builtins/regexp.tq @@ -6,8 +6,159 @@ namespace regexp { - extern macro RegExpBuiltinsAssembler::BranchIfFastRegExp( + extern macro RegExpBuiltinsAssembler::BranchIfFastRegExp_Strict( implicit context: Context)(HeapObject): never labels IsFast, IsSlow; + macro IsFastRegExpStrict(implicit context: Context)(o: HeapObject): bool { + BranchIfFastRegExp_Strict(o) otherwise return true, return false; + } + extern macro RegExpBuiltinsAssembler::BranchIfFastRegExp_Permissive( + implicit context: Context)(HeapObject): never labels IsFast, + IsSlow; + + @export + macro IsFastRegExpPermissive(implicit context: Context)(o: HeapObject): bool { + BranchIfFastRegExp_Permissive(o) otherwise return true, return false; + } + + extern macro RegExpBuiltinsAssembler::RegExpExec(Context, Object, Object): + Object; + + extern macro + RegExpBuiltinsAssembler::RegExpPrototypeExecBodyWithoutResultFast( + implicit context: Context)(JSRegExp, String): + RegExpMatchInfo labels IfDidNotMatch; + + extern macro RegExpBuiltinsAssembler::IsReceiverInitialRegExpPrototype( + implicit context: Context)(Object): bool; + + type Flag constexpr 'JSRegExp::Flag'; + const kGlobal: constexpr Flag + generates 'JSRegExp::kGlobal'; + const kIgnoreCase: constexpr Flag + generates 'JSRegExp::kIgnoreCase'; + const kMultiline: constexpr Flag + generates 'JSRegExp::kMultiline'; + const kDotAll: constexpr Flag + generates 'JSRegExp::kDotAll'; + const kSticky: constexpr Flag + generates 'JSRegExp::kSticky'; + const kUnicode: constexpr Flag + generates 'JSRegExp::kUnicode'; + + const kRegExpPrototypeOldFlagGetter: constexpr int31 + generates 'v8::Isolate::kRegExpPrototypeOldFlagGetter'; + const kRegExpPrototypeStickyGetter: constexpr int31 + generates 'v8::Isolate::kRegExpPrototypeStickyGetter'; + const kRegExpPrototypeUnicodeGetter: constexpr int31 + generates 'v8::Isolate::kRegExpPrototypeUnicodeGetter'; + + extern macro RegExpBuiltinsAssembler::FastFlagGetter( + JSRegExp, constexpr Flag): bool; + const kRegExpNonRegExp: constexpr MessageTemplate + generates 'MessageTemplate::kRegExpNonRegExp'; + extern runtime IncrementUseCounter(Context, Smi): void; + + macro FlagGetter(implicit context: Context)( + receiver: Object, flag: constexpr Flag, counter: constexpr int31, + methodName: constexpr string): JSAny { + typeswitch (receiver) { + case (receiver: JSRegExp): { + return SelectBooleanConstant(FastFlagGetter(receiver, flag)); + } + case (Object): { + } + } + if (!IsReceiverInitialRegExpPrototype(receiver)) { + ThrowTypeError(kRegExpNonRegExp, methodName); + } + if constexpr (counter != -1) { + IncrementUseCounter(context, SmiConstant(counter)); + } + return Undefined; + } + + // ES6 21.2.5.4. + // ES #sec-get-regexp.prototype.global + transitioning javascript builtin RegExpPrototypeGlobalGetter( + js-implicit context: Context, receiver: JSAny)(): JSAny { + return FlagGetter( + receiver, kGlobal, kRegExpPrototypeOldFlagGetter, + 'RegExp.prototype.global'); + } + + // ES6 21.2.5.5. + // ES #sec-get-regexp.prototype.ignorecase + transitioning javascript builtin RegExpPrototypeIgnoreCaseGetter( + js-implicit context: Context, receiver: JSAny)(): JSAny { + return FlagGetter( + receiver, kIgnoreCase, kRegExpPrototypeOldFlagGetter, + 'RegExp.prototype.ignoreCase'); + } + + // ES6 21.2.5.7. + // ES #sec-get-regexp.prototype.multiline + transitioning javascript builtin RegExpPrototypeMultilineGetter( + js-implicit context: Context, receiver: JSAny)(): JSAny { + return FlagGetter( + receiver, kMultiline, kRegExpPrototypeOldFlagGetter, + 'RegExp.prototype.multiline'); + } + + // ES #sec-get-regexp.prototype.dotAll + transitioning javascript builtin RegExpPrototypeDotAllGetter( + js-implicit context: Context, receiver: JSAny)(): JSAny { + const kNoCounter: constexpr int31 = -1; + return FlagGetter(receiver, kDotAll, kNoCounter, 'RegExp.prototype.dotAll'); + } + + // ES6 21.2.5.12. + // ES #sec-get-regexp.prototype.sticky + transitioning javascript builtin RegExpPrototypeStickyGetter( + js-implicit context: Context, receiver: JSAny)(): JSAny { + return FlagGetter( + receiver, kSticky, kRegExpPrototypeStickyGetter, + 'RegExp.prototype.sticky'); + } + + // ES6 21.2.5.15. + // ES #sec-get-regexp.prototype.unicode + transitioning javascript builtin RegExpPrototypeUnicodeGetter( + js-implicit context: Context, receiver: JSAny)(): JSAny { + return FlagGetter( + receiver, kUnicode, kRegExpPrototypeUnicodeGetter, + 'RegExp.prototype.unicode'); + } + + extern transitioning macro + RegExpBuiltinsAssembler::FlagsGetter(implicit context: Context)( + Object, constexpr bool): String; + + transitioning macro + FastFlagsGetter(implicit context: Context)(receiver: FastJSRegExp): String { + return FlagsGetter(receiver, true); + } + + transitioning macro SlowFlagsGetter(implicit context: + Context)(receiver: JSAny): String { + return FlagsGetter(receiver, false); + } + + const kRegExpNonObject: constexpr MessageTemplate + generates 'MessageTemplate::kRegExpNonObject'; + + // ES #sec-get-regexp.prototype.flags + // TFJ(RegExpPrototypeFlagsGetter, 0, kReceiver) \ + transitioning javascript builtin RegExpPrototypeFlagsGetter( + js-implicit context: Context, receiver: JSAny)(): String { + ThrowIfNotJSReceiver(receiver, kRegExpNonObject, 'RegExp.prototype.flags'); + + // The check is strict because the following code relies on individual flag + // getters on the regexp prototype (e.g.: global, sticky, ...). We don't + // bother to check these individually. + const fastRegexp = Cast<FastJSRegExp>(receiver) + otherwise return SlowFlagsGetter(receiver); + return FastFlagsGetter(fastRegexp); + } } diff --git a/deps/v8/src/builtins/s390/builtins-s390.cc b/deps/v8/src/builtins/s390/builtins-s390.cc index 854f31cece..7dca12d17e 100644 --- a/deps/v8/src/builtins/s390/builtins-s390.cc +++ b/deps/v8/src/builtins/s390/builtins-s390.cc @@ -81,12 +81,24 @@ static void GenerateTailCallToReturnedCode(MacroAssembler* masm, namespace { +MemOperand RealStackLimitAsMemOperand(MacroAssembler* masm) { + DCHECK(masm->root_array_available()); + Isolate* isolate = masm->isolate(); + ExternalReference limit = ExternalReference::address_of_real_jslimit(isolate); + DCHECK(TurboAssembler::IsAddressableThroughRootRegister(isolate, limit)); + + intptr_t offset = + TurboAssembler::RootRegisterOffsetForExternalReference(isolate, limit); + CHECK(is_int32(offset)); + return MemOperand(kRootRegister, offset); +} + 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); + __ LoadP(scratch, RealStackLimitAsMemOperand(masm)); // Make scratch the space we have left. The stack might already be overflowed // here which will cause scratch to become negative. __ SubP(scratch, sp, scratch); @@ -429,7 +441,8 @@ void Builtins::Generate_ResumeGeneratorTrampoline(MacroAssembler* masm) { // Check the stack for overflow. We are not trying to catch interruptions // (i.e. debug break and preemption) here, so check the "real stack limit". Label stack_overflow; - __ CompareRoot(sp, RootIndex::kRealStackLimit); + __ LoadP(scratch, RealStackLimitAsMemOperand(masm)); + __ CmpLogicalP(sp, scratch); __ blt(&stack_overflow); // Push receiver. @@ -772,7 +785,7 @@ static void Generate_CheckStackOverflow(MacroAssembler* masm, Register argc, // interruptions (e.g. debug break and preemption) here, so the "real stack // limit" is checked. Label okay; - __ LoadRoot(scratch1, RootIndex::kRealStackLimit); + __ LoadP(scratch1, RealStackLimitAsMemOperand(masm)); // Make scratch1 the space we have left. The stack might already be overflowed // here which will cause scratch1 to become negative. __ SubP(scratch1, sp, scratch1); @@ -1197,8 +1210,7 @@ void Builtins::Generate_InterpreterEntryTrampoline(MacroAssembler* masm) { // Do a stack check to ensure we don't go over the limit. Label ok; __ SubP(r8, sp, r4); - __ LoadRoot(r0, RootIndex::kRealStackLimit); - __ CmpLogicalP(r8, r0); + __ CmpLogicalP(r8, RealStackLimitAsMemOperand(masm)); __ bge(&ok); __ CallRuntime(Runtime::kThrowStackOverflow); __ bind(&ok); @@ -2219,7 +2231,7 @@ void Generate_PushBoundArguments(MacroAssembler* masm) { // Check the stack for overflow. We are not trying to catch interruptions // (i.e. debug break and preemption) here, so check the "real stack // limit". - __ CompareRoot(sp, RootIndex::kRealStackLimit); + __ CmpLogicalP(sp, RealStackLimitAsMemOperand(masm)); __ bgt(&done); // Signed comparison. // Restore the stack pointer. __ LoadRR(sp, scratch); @@ -2657,7 +2669,10 @@ void Builtins::Generate_WasmCompileLazy(MacroAssembler* masm) { __ Push(kWasmInstanceRegister, r7); // Load the correct CEntry builtin from the instance object. __ LoadP(r4, FieldMemOperand(kWasmInstanceRegister, - WasmInstanceObject::kCEntryStubOffset)); + WasmInstanceObject::kIsolateRootOffset)); + auto centry_id = + Builtins::kCEntry_Return1_DontSaveFPRegs_ArgvOnStack_NoBuiltinExit; + __ LoadP(r4, MemOperand(r4, IsolateData::builtin_slot_offset(centry_id))); // Initialize the JavaScript context with 0. CEntry will use it to // set the current context on the isolate. __ LoadSmiLiteral(cp, Smi::zero()); diff --git a/deps/v8/src/builtins/setup-builtins-internal.cc b/deps/v8/src/builtins/setup-builtins-internal.cc index 3c637db636..99ac0d6b1f 100644 --- a/deps/v8/src/builtins/setup-builtins-internal.cc +++ b/deps/v8/src/builtins/setup-builtins-internal.cc @@ -119,9 +119,9 @@ Code BuildWithMacroAssembler(Isolate* isolate, int32_t builtin_index, .set_self_reference(masm.CodeObject()) .set_builtin_index(builtin_index) .Build(); -#if defined(V8_OS_WIN_X64) +#if defined(V8_OS_WIN64) isolate->SetBuiltinUnwindData(builtin_index, masm.GetUnwindInfo()); -#endif +#endif // V8_OS_WIN64 return *code; } @@ -276,10 +276,6 @@ Code GenerateBytecodeHandler(Isolate* isolate, int builtin_index, } // namespace -#ifdef _MSC_VER -#pragma optimize( "", off ) -#endif - // static void SetupIsolateDelegate::SetupBuiltinsInternal(Isolate* isolate) { Builtins* builtins = isolate->builtins(); @@ -357,10 +353,5 @@ void SetupIsolateDelegate::SetupBuiltinsInternal(Isolate* isolate) { builtins->MarkInitialized(); } -#ifdef _MSC_VER -#pragma optimize( "", on ) -#endif - - } // namespace internal } // namespace v8 diff --git a/deps/v8/src/builtins/string-endswith.tq b/deps/v8/src/builtins/string-endswith.tq index 8b9fe84dfb..c3cc7d949b 100644 --- a/deps/v8/src/builtins/string-endswith.tq +++ b/deps/v8/src/builtins/string-endswith.tq @@ -28,13 +28,13 @@ namespace string { // https://tc39.github.io/ecma262/#sec-string.prototype.endswith transitioning javascript builtin StringPrototypeEndsWith( - js-implicit context: Context, receiver: Object)(...arguments): Boolean { - const searchString: Object = arguments[0]; - const endPosition: Object = arguments[1]; + js-implicit context: Context, receiver: JSAny)(...arguments): Boolean { + const searchString: JSAny = arguments[0]; + const endPosition: JSAny = arguments[1]; const kBuiltinName: constexpr string = 'String.prototype.endsWith'; // 1. Let O be ? RequireObjectCoercible(this value). - const object: Object = RequireObjectCoercible(receiver, kBuiltinName); + const object: JSAny = RequireObjectCoercible(receiver, kBuiltinName); // 2. Let S be ? ToString(O). const string: String = ToString_Inline(context, object); diff --git a/deps/v8/src/builtins/string-html.tq b/deps/v8/src/builtins/string-html.tq index 80b5f77887..0b0fdfeaef 100644 --- a/deps/v8/src/builtins/string-html.tq +++ b/deps/v8/src/builtins/string-html.tq @@ -7,8 +7,8 @@ namespace string_html { // https://tc39.github.io/ecma262/#sec-createhtml transitioning builtin CreateHTML(implicit context: Context)( - receiver: Object, methodName: String, tagName: String, attr: String, - attrValue: Object): String { + receiver: JSAny, methodName: String, tagName: String, attr: String, + attrValue: JSAny): String { const tagContents: String = ToThisString(receiver, methodName); let result = '<' + tagName; if (attr != kEmptyString) { @@ -22,14 +22,14 @@ namespace string_html { // https://tc39.github.io/ecma262/#sec-string.prototype.anchor transitioning javascript builtin StringPrototypeAnchor( - js-implicit context: Context, receiver: Object)(...arguments): String { + js-implicit context: Context, receiver: JSAny)(...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(js-implicit context: Context, receiver: Object)( + StringPrototypeBig(js-implicit context: Context, receiver: JSAny)( ...arguments): String { return CreateHTML( receiver, 'String.prototype.big', 'big', kEmptyString, kEmptyString); @@ -37,7 +37,7 @@ namespace string_html { // https://tc39.github.io/ecma262/#sec-string.prototype.blink transitioning javascript builtin - StringPrototypeBlink(js-implicit context: Context, receiver: Object)( + StringPrototypeBlink(js-implicit context: Context, receiver: JSAny)( ...arguments): String { return CreateHTML( receiver, 'String.prototype.blink', 'blink', kEmptyString, @@ -46,7 +46,7 @@ namespace string_html { // https://tc39.github.io/ecma262/#sec-string.prototype.bold transitioning javascript builtin - StringPrototypeBold(js-implicit context: Context, receiver: Object)( + StringPrototypeBold(js-implicit context: Context, receiver: JSAny)( ...arguments): String { return CreateHTML( receiver, 'String.prototype.bold', 'b', kEmptyString, kEmptyString); @@ -54,7 +54,7 @@ namespace string_html { // https://tc39.github.io/ecma262/#sec-string.prototype.fontcolor transitioning javascript builtin - StringPrototypeFontcolor(js-implicit context: Context, receiver: Object)( + StringPrototypeFontcolor(js-implicit context: Context, receiver: JSAny)( ...arguments): String { return CreateHTML( receiver, 'String.prototype.fontcolor', 'font', 'color', arguments[0]); @@ -62,7 +62,7 @@ namespace string_html { // https://tc39.github.io/ecma262/#sec-string.prototype.fontsize transitioning javascript builtin - StringPrototypeFontsize(js-implicit context: Context, receiver: Object)( + StringPrototypeFontsize(js-implicit context: Context, receiver: JSAny)( ...arguments): String { return CreateHTML( receiver, 'String.prototype.fontsize', 'font', 'size', arguments[0]); @@ -70,7 +70,7 @@ namespace string_html { // https://tc39.github.io/ecma262/#sec-string.prototype.fixed transitioning javascript builtin - StringPrototypeFixed(js-implicit context: Context, receiver: Object)( + StringPrototypeFixed(js-implicit context: Context, receiver: JSAny)( ...arguments): String { return CreateHTML( receiver, 'String.prototype.fixed', 'tt', kEmptyString, kEmptyString); @@ -78,7 +78,7 @@ namespace string_html { // https://tc39.github.io/ecma262/#sec-string.prototype.italics transitioning javascript builtin - StringPrototypeItalics(js-implicit context: Context, receiver: Object)( + StringPrototypeItalics(js-implicit context: Context, receiver: JSAny)( ...arguments): String { return CreateHTML( receiver, 'String.prototype.italics', 'i', kEmptyString, kEmptyString); @@ -86,7 +86,7 @@ namespace string_html { // https://tc39.github.io/ecma262/#sec-string.prototype.link transitioning javascript builtin - StringPrototypeLink(js-implicit context: Context, receiver: Object)( + StringPrototypeLink(js-implicit context: Context, receiver: JSAny)( ...arguments): String { return CreateHTML( receiver, 'String.prototype.link', 'a', 'href', arguments[0]); @@ -94,7 +94,7 @@ namespace string_html { // https://tc39.github.io/ecma262/#sec-string.prototype.small transitioning javascript builtin - StringPrototypeSmall(js-implicit context: Context, receiver: Object)( + StringPrototypeSmall(js-implicit context: Context, receiver: JSAny)( ...arguments): String { return CreateHTML( receiver, 'String.prototype.small', 'small', kEmptyString, @@ -103,7 +103,7 @@ namespace string_html { // https://tc39.github.io/ecma262/#sec-string.prototype.strike transitioning javascript builtin - StringPrototypeStrike(js-implicit context: Context, receiver: Object)( + StringPrototypeStrike(js-implicit context: Context, receiver: JSAny)( ...arguments): String { return CreateHTML( receiver, 'String.prototype.strike', 'strike', kEmptyString, @@ -112,7 +112,7 @@ namespace string_html { // https://tc39.github.io/ecma262/#sec-string.prototype.sub transitioning javascript builtin - StringPrototypeSub(js-implicit context: Context, receiver: Object)( + StringPrototypeSub(js-implicit context: Context, receiver: JSAny)( ...arguments): String { return CreateHTML( receiver, 'String.prototype.sub', 'sub', kEmptyString, kEmptyString); @@ -120,7 +120,7 @@ namespace string_html { // https://tc39.github.io/ecma262/#sec-string.prototype.sup transitioning javascript builtin - StringPrototypeSup(js-implicit context: Context, receiver: Object)( + StringPrototypeSup(js-implicit context: Context, receiver: JSAny)( ...arguments): String { return CreateHTML( receiver, 'String.prototype.sup', 'sup', kEmptyString, kEmptyString); diff --git a/deps/v8/src/builtins/string-iterator.tq b/deps/v8/src/builtins/string-iterator.tq index 5b8f864661..d36a44fa97 100644 --- a/deps/v8/src/builtins/string-iterator.tq +++ b/deps/v8/src/builtins/string-iterator.tq @@ -17,7 +17,7 @@ namespace string_iterator { // ES6 #sec-string.prototype-@@iterator transitioning javascript builtin StringPrototypeIterator( - js-implicit context: Context)(receiver: Object): JSStringIterator { + js-implicit context: Context, receiver: JSAny)(): JSStringIterator { const name: String = ToThisString(receiver, 'String.prototype[Symbol.iterator]'); const index: Smi = 0; @@ -26,7 +26,7 @@ namespace string_iterator { // ES6 #sec-%stringiteratorprototype%.next transitioning javascript builtin StringIteratorPrototypeNext( - js-implicit context: Context)(receiver: Object): JSObject { + js-implicit context: Context, receiver: JSAny)(): JSObject { const iterator = Cast<JSStringIterator>(receiver) otherwise ThrowTypeError( kIncompatibleMethodReceiver, 'String Iterator.prototype.next', receiver); diff --git a/deps/v8/src/builtins/string-pad.tq b/deps/v8/src/builtins/string-pad.tq new file mode 100644 index 0000000000..2368067c4e --- /dev/null +++ b/deps/v8/src/builtins/string-pad.tq @@ -0,0 +1,111 @@ +// 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-string-gen.h' + +namespace string { + + extern transitioning builtin + StringSubstring(implicit context: Context)(String, intptr, intptr): String; + + const kStringPadStart: constexpr int31 = 0; + const kStringPadEnd: constexpr int31 = 1; + + transitioning macro StringPad(implicit context: Context)( + receiver: JSAny, arguments: Arguments, methodName: constexpr string, + variant: constexpr int31): String { + const receiverString: String = ToThisString(receiver, methodName); + const stringLength: Smi = receiverString.length_smi; + + if (arguments.length == 0) { + return receiverString; + } + const maxLength: Number = ToLength_Inline(context, arguments[0]); + assert(IsNumberNormalized(maxLength)); + + typeswitch (maxLength) { + case (smiMaxLength: Smi): { + if (smiMaxLength <= stringLength) { + return receiverString; + } + } + case (Number): { + } + } + + let fillString: String = ' '; + let fillLength: intptr = 1; + + if (arguments.length != 1) { + const fill = arguments[1]; + if (fill != Undefined) { + fillString = ToString_Inline(context, fill); + fillLength = fillString.length_intptr; + if (fillLength == 0) { + return receiverString; + } + } + } + + // Pad. + assert(fillLength > 0); + // Throw if max_length is greater than String::kMaxLength. + if (!TaggedIsSmi(maxLength)) { + ThrowInvalidStringLength(context); + } + + const smiMaxLength: Smi = UnsafeCast<Smi>(maxLength); + if (smiMaxLength > SmiConstant(kStringMaxLength)) { + ThrowInvalidStringLength(context); + } + assert(smiMaxLength > stringLength); + const padLength: Smi = smiMaxLength - stringLength; + + let padding: String; + if (fillLength == 1) { + // Single char fill. + // Fast path for a single character fill. No need to calculate number of + // repetitions or remainder. + padding = StringRepeat(context, fillString, padLength); + } else { + // Multi char fill. + const fillLengthWord32: int32 = TruncateIntPtrToInt32(fillLength); + const padLengthWord32: int32 = Convert<int32>(padLength); + const repetitionsWord32: int32 = padLengthWord32 / fillLengthWord32; + const remainingWord32: int32 = padLengthWord32 % fillLengthWord32; + padding = + StringRepeat(context, fillString, Convert<Smi>(repetitionsWord32)); + + if (remainingWord32 != 0) { + const remainderString = + StringSubstring(fillString, 0, Convert<intptr>(remainingWord32)); + padding = padding + remainderString; + } + } + + // Return result. + assert(padLength == padding.length_smi); + if (variant == kStringPadStart) { + return padding + receiverString; + } + assert(variant == kStringPadEnd); + return receiverString + padding; + } + + // ES6 #sec-string.prototype.padstart + transitioning javascript builtin + StringPrototypePadStart(js-implicit context: Context, receiver: JSAny)( + ...arguments): String { + const methodName: constexpr string = 'String.prototype.padStart'; + return StringPad(receiver, arguments, methodName, kStringPadStart); + } + + // ES6 #sec-string.prototype.padend + transitioning javascript builtin + StringPrototypePadEnd(js-implicit context: Context, receiver: JSAny)( + ...arguments): String { + const methodName: constexpr string = 'String.prototype.padEnd'; + return StringPad(receiver, arguments, methodName, kStringPadEnd); + } +} diff --git a/deps/v8/src/builtins/string-repeat.tq b/deps/v8/src/builtins/string-repeat.tq index 0d9d4ee498..f341ed4336 100644 --- a/deps/v8/src/builtins/string-repeat.tq +++ b/deps/v8/src/builtins/string-repeat.tq @@ -28,7 +28,7 @@ namespace string_repeat { // https://tc39.github.io/ecma262/#sec-string.prototype.repeat transitioning javascript builtin StringPrototypeRepeat( - js-implicit context: Context, receiver: Object)(count: Object): String { + js-implicit context: Context, receiver: JSAny)(count: JSAny): String { // 1. Let O be ? RequireObjectCoercible(this value). // 2. Let S be ? ToString(O). const s: String = ToThisString(receiver, kBuiltinName); diff --git a/deps/v8/src/builtins/string-slice.tq b/deps/v8/src/builtins/string-slice.tq index b066fb7669..661cc264c5 100644 --- a/deps/v8/src/builtins/string-slice.tq +++ b/deps/v8/src/builtins/string-slice.tq @@ -9,7 +9,7 @@ namespace string_slice { // ES6 #sec-string.prototype.slice ( start, end ) // https://tc39.github.io/ecma262/#sec-string.prototype.slice transitioning javascript builtin StringPrototypeSlice( - js-implicit context: Context, receiver: Object)(...arguments): String { + js-implicit context: Context, receiver: JSAny)(...arguments): String { // 1. Let O be ? RequireObjectCoercible(this value). // 2. Let S be ? ToString(O). const string: String = ToThisString(receiver, 'String.prototype.slice'); diff --git a/deps/v8/src/builtins/string-startswith.tq b/deps/v8/src/builtins/string-startswith.tq index b03e67ecf5..7fa7ec6d5c 100644 --- a/deps/v8/src/builtins/string-startswith.tq +++ b/deps/v8/src/builtins/string-startswith.tq @@ -10,13 +10,13 @@ namespace string { // https://tc39.github.io/ecma262/#sec-string.prototype.startswith transitioning javascript builtin StringPrototypeStartsWith( - js-implicit context: Context, receiver: Object)(...arguments): Boolean { - const searchString: Object = arguments[0]; - const position: Object = arguments[1]; + js-implicit context: Context, receiver: JSAny)(...arguments): Boolean { + const searchString: JSAny = arguments[0]; + const position: JSAny = arguments[1]; const kBuiltinName: constexpr string = 'String.prototype.startsWith'; // 1. Let O be ? RequireObjectCoercible(this value). - const object: Object = RequireObjectCoercible(receiver, kBuiltinName); + const object: JSAny = RequireObjectCoercible(receiver, kBuiltinName); // 2. Let S be ? ToString(O). const string: String = ToString_Inline(context, object); diff --git a/deps/v8/src/builtins/string-substring.tq b/deps/v8/src/builtins/string-substring.tq index 1fafb8af43..c97b294a34 100644 --- a/deps/v8/src/builtins/string-substring.tq +++ b/deps/v8/src/builtins/string-substring.tq @@ -7,7 +7,7 @@ namespace string_substring { extern macro SubString(String, intptr, intptr): String; transitioning macro ToSmiBetweenZeroAnd(implicit context: Context)( - value: Object, limit: Smi): Smi { + value: JSAny, limit: Smi): Smi { const valueInt: Number = ToInteger_Inline(context, value, kTruncateMinusZero); typeswitch (valueInt) { @@ -28,7 +28,7 @@ namespace string_substring { // ES6 #sec-string.prototype.substring transitioning javascript builtin StringPrototypeSubstring( - js-implicit context: Context, receiver: Object)(...arguments): String { + js-implicit context: Context, receiver: JSAny)(...arguments): String { // Check that {receiver} is coercible to Object and convert it to a String. const string: String = ToThisString(receiver, 'String.prototype.substring'); const length = string.length_smi; diff --git a/deps/v8/src/builtins/string.tq b/deps/v8/src/builtins/string.tq index dbcc5799e1..7f007680e9 100644 --- a/deps/v8/src/builtins/string.tq +++ b/deps/v8/src/builtins/string.tq @@ -7,15 +7,15 @@ namespace string { // ES6 #sec-string.prototype.tostring transitioning javascript builtin - StringPrototypeToString(js-implicit context: Context)(receiver: Object): - Object { + StringPrototypeToString(js-implicit context: Context, receiver: JSAny)(): + JSAny { return ToThisValue(receiver, kString, 'String.prototype.toString'); } // ES6 #sec-string.prototype.valueof transitioning javascript builtin - StringPrototypeValueOf(js-implicit context: Context)(receiver: Object): - Object { + StringPrototypeValueOf(js-implicit context: Context, receiver: JSAny)(): + JSAny { return ToThisValue(receiver, kString, 'String.prototype.valueOf'); } @@ -29,7 +29,8 @@ namespace string { const kind = PACKED_ELEMENTS; const stringLength: intptr = string.length_intptr; - const map: Map = LoadJSArrayElementsMap(kind, LoadNativeContext(context)); + const nativeContext = LoadNativeContext(context); + const map: Map = LoadJSArrayElementsMap(kind, nativeContext); const array: JSArray = AllocateJSArray( kind, map, stringLength, SmiTag(stringLength), kAllowLargeObjectAllocation); @@ -53,7 +54,7 @@ namespace string { } transitioning macro GenerateStringAt(implicit context: Context)( - receiver: Object, position: Object, + receiver: JSAny, position: JSAny, methodName: constexpr string): never labels IfInBounds(String, intptr, intptr), IfOutOfBounds { // Check that {receiver} is coercible to Object and convert it to a String. @@ -71,8 +72,7 @@ namespace string { // ES6 #sec-string.prototype.charat transitioning javascript builtin StringPrototypeCharAt( - js-implicit context: Context, - receiver: Object)(position: Object): Object { + js-implicit context: Context, receiver: JSAny)(position: JSAny): JSAny { try { GenerateStringAt(receiver, position, 'String.prototype.charAt') otherwise IfInBounds, IfOutOfBounds; @@ -88,8 +88,7 @@ namespace string { // ES6 #sec-string.prototype.charcodeat transitioning javascript builtin StringPrototypeCharCodeAt( - js-implicit context: Context, - receiver: Object)(position: Object): Object { + js-implicit context: Context, receiver: JSAny)(position: JSAny): JSAny { try { GenerateStringAt(receiver, position, 'String.prototype.charCodeAt') otherwise IfInBounds, IfOutOfBounds; @@ -105,8 +104,7 @@ namespace string { // ES6 #sec-string.prototype.codepointat transitioning javascript builtin StringPrototypeCodePointAt( - js-implicit context: Context, - receiver: Object)(position: Object): Object { + js-implicit context: Context, receiver: JSAny)(position: JSAny): JSAny { try { GenerateStringAt(receiver, position, 'String.prototype.codePointAt') otherwise IfInBounds, IfOutOfBounds; @@ -125,7 +123,7 @@ namespace string { // ES6 String.prototype.concat(...args) // ES6 #sec-string.prototype.concat transitioning javascript builtin StringPrototypeConcat( - js-implicit context: Context, receiver: Object)(...arguments): Object { + js-implicit context: Context, receiver: JSAny)(...arguments): JSAny { // Check that {receiver} is coercible to Object and convert it to a String. let string: String = ToThisString(receiver, 'String.prototype.concat'); @@ -137,4 +135,56 @@ namespace string { } return string; } + + extern transitioning runtime + SymbolDescriptiveString(implicit context: Context)(Symbol): String; + + // ES #sec-string-constructor + // https://tc39.github.io/ecma262/#sec-string-constructor + transitioning javascript builtin StringConstructor( + js-implicit context: Context, receiver: JSAny, newTarget: JSAny, + target: JSFunction)(...arguments): JSAny { + const length: intptr = Convert<intptr>(arguments.length); + let s: String; + // 1. If no arguments were passed to this function invocation, let s be "". + if (length == 0) { + s = EmptyStringConstant(); + } else { + // 2. Else, + // 2. a. If NewTarget is undefined and Type(value) is Symbol, return + // SymbolDescriptiveString(value). + if (newTarget == Undefined) { + typeswitch (arguments[0]) { + case (value: Symbol): { + return SymbolDescriptiveString(value); + } + case (JSAny): { + } + } + } + // 2. b. Let s be ? ToString(value). + s = ToString_Inline(context, arguments[0]); + } + // 3. If NewTarget is undefined, return s. + if (newTarget == Undefined) { + return s; + } + // 4. Return ! StringCreate(s, ? GetPrototypeFromConstructor(NewTarget, + // "%String.prototype%")). + const map = GetDerivedMap(target, UnsafeCast<JSReceiver>(newTarget)); + const obj = + UnsafeCast<JSPrimitiveWrapper>(AllocateFastOrSlowJSObjectFromMap(map)); + obj.value = s; + return obj; + } + + transitioning builtin StringAddConvertLeft(implicit context: Context)( + left: JSAny, right: String): String { + return ToStringImpl(context, ToPrimitiveDefault(left)) + right; + } + + transitioning builtin StringAddConvertRight(implicit context: Context)( + left: String, right: JSAny): String { + return left + ToStringImpl(context, ToPrimitiveDefault(right)); + } } diff --git a/deps/v8/src/builtins/torque-internal.tq b/deps/v8/src/builtins/torque-internal.tq new file mode 100644 index 0000000000..48a08deb0a --- /dev/null +++ b/deps/v8/src/builtins/torque-internal.tq @@ -0,0 +1,106 @@ +// 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 torque_internal { + // TODO(gsps): Synthesize SizeOf<T> in the compiler + + macro SizeOf<T: type>(): constexpr int31; + SizeOf<Object>(): constexpr int31 { + return kTaggedSize; + } + SizeOf<float64>(): constexpr int31 { + return kDoubleSize; + } + + // Unsafe is a marker that we require to be passed when calling internal APIs + // that might lead to unsoundness when used incorrectly. Unsafe markers should + // therefore not be instantiated anywhere outside of this namespace. + struct Unsafe {} + + struct Reference<T: type> { + const object: HeapObject; + const offset: intptr; + unsafeMarker: Unsafe; + } + + macro UnsafeNewReference<T: type>(object: HeapObject, offset: intptr):&T { + return Reference<T>{ + object: object, + offset: offset, + unsafeMarker: Unsafe {} + }; + } + + struct Slice<T: type> { + TryAtIndex(index: intptr):&T labels OutOfBounds { + if (Convert<uintptr>(index) < Convert<uintptr>(this.length)) { + return UnsafeNewReference<T>( + this.object, this.offset + index * SizeOf<T>()); + } else { + goto OutOfBounds; + } + } + + AtIndex(index: intptr):&T { + return this.TryAtIndex(index) otherwise unreachable; + } + + AtIndex(index: constexpr int31):&T { + const i: intptr = Convert<intptr>(index); + return this.TryAtIndex(i) otherwise unreachable; + } + + AtIndex(index: Smi):&T { + const i: intptr = Convert<intptr>(index); + return this.TryAtIndex(i) otherwise unreachable; + } + + Iterator(): SliceIterator<T> { + const end = this.offset + this.length * SizeOf<T>(); + return SliceIterator<T>{ + object: this.object, + start: this.offset, + end: end, + unsafeMarker: Unsafe {} + }; + } + + const object: HeapObject; + const offset: intptr; + const length: intptr; + unsafeMarker: Unsafe; + } + + macro UnsafeNewSlice<T: type>( + object: HeapObject, offset: intptr, length: intptr): Slice<T> { + return Slice<T>{ + object: object, + offset: offset, + length: length, + unsafeMarker: Unsafe {} + }; + } + + struct SliceIterator<T: type> { + Empty(): bool { + return this.start == this.end; + } + + Next():&T labels NoMore { + if (this.Empty()) { + goto NoMore; + } else { + const result = UnsafeNewReference<T>(this.object, this.start); + this.start += SizeOf<T>(); + return result; + } + } + + object: HeapObject; + start: intptr; + end: intptr; + unsafeMarker: Unsafe; + } + +} // namespace torque_internal diff --git a/deps/v8/src/builtins/typed-array-createtypedarray.tq b/deps/v8/src/builtins/typed-array-createtypedarray.tq index f6ab289e12..a476739861 100644 --- a/deps/v8/src/builtins/typed-array-createtypedarray.tq +++ b/deps/v8/src/builtins/typed-array-createtypedarray.tq @@ -122,7 +122,7 @@ namespace typed_array_createtypedarray { // 22.2.4.2 TypedArray ( length ) // ES #sec-typedarray-length transitioning macro ConstructByLength(implicit context: Context)( - map: Map, length: Object, + map: Map, length: JSAny, elementsInfo: typed_array::TypedArrayElementsInfo): JSTypedArray { const convertedLength: Number = ToInteger_Inline(context, length, kTruncateMinusZero); @@ -141,7 +141,7 @@ namespace typed_array_createtypedarray { // 22.2.4.4 TypedArray ( object ) // ES #sec-typedarray-object transitioning macro ConstructByArrayLike(implicit context: Context)( - map: Map, arrayLike: HeapObject, initialLength: Object, + map: Map, arrayLike: HeapObject, initialLength: JSAny, elementsInfo: typed_array::TypedArrayElementsInfo, bufferConstructor: JSReceiver): JSTypedArray { // The caller has looked up length on arrayLike, which is observable. @@ -178,7 +178,7 @@ namespace typed_array_createtypedarray { // ES #sec-typedarray-object transitioning macro ConstructByIterable(implicit context: Context)( iterable: JSReceiver, iteratorFn: Callable): never - labels IfConstructByArrayLike(HeapObject, Object, JSReceiver) { + labels IfConstructByArrayLike(JSArray, Number, JSReceiver) { const array: JSArray = IterableToListMayPreserveHoles(context, iterable, iteratorFn); goto IfConstructByArrayLike(array, array.length, GetArrayBufferFunction()); @@ -188,7 +188,7 @@ namespace typed_array_createtypedarray { // ES #sec-typedarray-typedarray transitioning macro ConstructByTypedArray(implicit context: Context)( srcTypedArray: JSTypedArray): never - labels IfConstructByArrayLike(HeapObject, Object, JSReceiver) { + labels IfConstructByArrayLike(JSTypedArray, Number, JSReceiver) { let bufferConstructor: JSReceiver = GetArrayBufferFunction(); const srcBuffer: JSArrayBuffer = srcTypedArray.buffer; // TODO(petermarshall): Throw on detached typedArray. @@ -210,7 +210,7 @@ namespace typed_array_createtypedarray { // 22.2.4.5 TypedArray ( buffer, byteOffset, length ) // ES #sec-typedarray-buffer-byteoffset-length transitioning macro ConstructByArrayBuffer(implicit context: Context)( - map: Map, buffer: JSArrayBuffer, byteOffset: Object, length: Object, + map: Map, buffer: JSArrayBuffer, byteOffset: JSAny, length: JSAny, elementsInfo: typed_array::TypedArrayElementsInfo): JSTypedArray { try { let offset: uintptr = 0; @@ -294,7 +294,7 @@ namespace typed_array_createtypedarray { transitioning macro ConstructByJSReceiver(implicit context: Context)(obj: JSReceiver): never - labels IfConstructByArrayLike(HeapObject, Object, JSReceiver) { + labels IfConstructByArrayLike(JSReceiver, Number, JSReceiver) { try { const iteratorMethod: Object = GetIteratorMethod(obj) otherwise IfIteratorUndefined; @@ -304,7 +304,7 @@ namespace typed_array_createtypedarray { otherwise IfConstructByArrayLike; } label IfIteratorUndefined { - const lengthObj: Object = GetProperty(obj, kLengthString); + const lengthObj: JSAny = GetProperty(obj, kLengthString); const length: Smi = ToSmiLength(lengthObj) otherwise goto IfInvalidLength(lengthObj); goto IfConstructByArrayLike(obj, length, GetArrayBufferFunction()); @@ -317,8 +317,8 @@ namespace typed_array_createtypedarray { // 22.2.4 The TypedArray Constructors // ES #sec-typedarray-constructors transitioning builtin CreateTypedArray( - context: Context, target: JSFunction, newTarget: JSReceiver, arg1: Object, - arg2: Object, arg3: Object): JSTypedArray { + context: Context, target: JSFunction, newTarget: JSReceiver, arg1: JSAny, + arg2: JSAny, arg3: JSAny): JSTypedArray { assert(IsConstructor(target)); // 4. Let O be ? AllocateTypedArray(constructorName, NewTarget, // "%TypedArrayPrototype%"). @@ -345,16 +345,16 @@ namespace typed_array_createtypedarray { } // The first argument was a number or fell through and is treated as // a number. https://tc39.github.io/ecma262/#sec-typedarray-length - case (lengthObj: HeapObject): { + case (lengthObj: JSAny): { goto IfConstructByLength(lengthObj); } } } - label IfConstructByLength(length: Object) { + label IfConstructByLength(length: JSAny) { return ConstructByLength(map, length, elementsInfo); } label IfConstructByArrayLike( - arrayLike: HeapObject, length: Object, bufferConstructor: JSReceiver) { + arrayLike: JSReceiver, length: Number, bufferConstructor: JSReceiver) { return ConstructByArrayLike( map, arrayLike, length, elementsInfo, bufferConstructor); } @@ -362,8 +362,8 @@ namespace typed_array_createtypedarray { transitioning macro TypedArraySpeciesCreate(implicit context: Context)( methodName: constexpr string, numArgs: constexpr int31, - exemplar: JSTypedArray, arg0: Object, arg1: Object, - arg2: Object): JSTypedArray { + exemplar: JSTypedArray, arg0: JSAny, arg1: JSAny, + arg2: JSAny): JSTypedArray { const defaultConstructor = GetDefaultConstructor(exemplar); try { @@ -386,7 +386,7 @@ namespace typed_array_createtypedarray { // TODO(pwong): Simplify and remove numArgs when varargs are supported in // macros. - let newObj: Object = Undefined; + let newObj: JSAny = Undefined; if constexpr (numArgs == 1) { newObj = Construct(constructor, arg0); } else { diff --git a/deps/v8/src/builtins/typed-array-every.tq b/deps/v8/src/builtins/typed-array-every.tq index 221814cb79..4b4fe72eb1 100644 --- a/deps/v8/src/builtins/typed-array-every.tq +++ b/deps/v8/src/builtins/typed-array-every.tq @@ -9,7 +9,7 @@ namespace typed_array_every { transitioning macro EveryAllElements(implicit context: Context)( array: typed_array::AttachedJSTypedArray, callbackfn: Callable, - thisArg: Object): Boolean { + thisArg: JSAny): Boolean { let witness = typed_array::NewAttachedJSTypedArrayWitness(array); // TODO(v8:4153): Support huge TypedArrays here. const length = @@ -17,7 +17,7 @@ namespace typed_array_every { 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 value: JSAny = witness.Load(k); const result = Call(context, callbackfn, thisArg, value, k, witness.GetStable()); if (!ToBoolean(result)) { @@ -29,8 +29,8 @@ namespace typed_array_every { // https://tc39.github.io/ecma262/#sec-%typedarray%.prototype.every transitioning javascript builtin - TypedArrayPrototypeEvery(js-implicit context: Context, receiver: Object)( - ...arguments): Object { + TypedArrayPrototypeEvery(js-implicit context: Context, receiver: JSAny)( + ...arguments): JSAny { // arguments[0] = callback // arguments[1] = thisArg try { diff --git a/deps/v8/src/builtins/typed-array-filter.tq b/deps/v8/src/builtins/typed-array-filter.tq index 3937699c73..66823f29e1 100644 --- a/deps/v8/src/builtins/typed-array-filter.tq +++ b/deps/v8/src/builtins/typed-array-filter.tq @@ -10,7 +10,7 @@ namespace typed_array_filter { // https://tc39.github.io/ecma262/#sec-%typedarray%.prototype.filter transitioning javascript builtin TypedArrayPrototypeFilter( - js-implicit context: Context, receiver: Object)(...arguments): Object { + js-implicit context: Context, receiver: JSAny)(...arguments): JSAny { // arguments[0] = callback // arguments[1] = thisArg try { @@ -29,7 +29,7 @@ namespace typed_array_filter { otherwise ThrowTypeError(kCalledNonCallable, arguments[0]); // 5. If thisArg is present, let T be thisArg; else let T be undefined. - const thisArg: Object = arguments[1]; + const thisArg: JSAny = arguments[1]; // 6. Let kept be a new empty List. let kept = growable_fixed_array::NewGrowableFixedArray(); @@ -43,17 +43,17 @@ namespace typed_array_filter { // a. Let Pk be ! ToString(k). // b. Let kValue be ? Get(O, Pk). - const value: Object = witness.Load(k); + const value: JSAny = witness.Load(k); // c. Let selected be ToBoolean(? Call(callbackfn, T, « kValue, k, O // »)). - const selected: Object = + const selected: JSAny = Call(context, callbackfn, thisArg, value, k, witness.GetStable()); // d. If selected is true, then // i. Append kValue to the end of kept. // ii. Increase captured by 1. - if (BranchIfToBooleanIsTrue(selected)) kept.Push(value); + if (ToBoolean(selected)) kept.Push(value); // e.Increase k by 1. } diff --git a/deps/v8/src/builtins/typed-array-find.tq b/deps/v8/src/builtins/typed-array-find.tq index be1943ccf4..9922abdc17 100644 --- a/deps/v8/src/builtins/typed-array-find.tq +++ b/deps/v8/src/builtins/typed-array-find.tq @@ -9,7 +9,7 @@ namespace typed_array_find { transitioning macro FindAllElements(implicit context: Context)( array: typed_array::AttachedJSTypedArray, callbackfn: Callable, - thisArg: Object): Object { + thisArg: JSAny): JSAny { let witness = typed_array::NewAttachedJSTypedArrayWitness(array); // TODO(v8:4153): Support huge TypedArrays here. const length = @@ -17,7 +17,7 @@ namespace typed_array_find { 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 value: JSAny = witness.Load(k); const result = Call(context, callbackfn, thisArg, value, k, witness.GetStable()); if (ToBoolean(result)) { @@ -29,8 +29,8 @@ namespace typed_array_find { // https://tc39.github.io/ecma262/#sec-%typedarray%.prototype.find transitioning javascript builtin - TypedArrayPrototypeFind(js-implicit context: Context, receiver: Object)( - ...arguments): Object { + TypedArrayPrototypeFind(js-implicit context: Context, receiver: JSAny)( + ...arguments): JSAny { // arguments[0] = callback // arguments[1] = thisArg try { diff --git a/deps/v8/src/builtins/typed-array-findindex.tq b/deps/v8/src/builtins/typed-array-findindex.tq index a5ee7897d3..5438f3dbfe 100644 --- a/deps/v8/src/builtins/typed-array-findindex.tq +++ b/deps/v8/src/builtins/typed-array-findindex.tq @@ -9,7 +9,7 @@ namespace typed_array_findindex { transitioning macro FindIndexAllElements(implicit context: Context)( array: typed_array::AttachedJSTypedArray, callbackfn: Callable, - thisArg: Object): Number { + thisArg: JSAny): Number { let witness = typed_array::NewAttachedJSTypedArrayWitness(array); // TODO(v8:4153): Support huge TypedArrays here. const length = @@ -17,7 +17,7 @@ namespace typed_array_findindex { 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 value: JSAny = witness.Load(k); const result = Call(context, callbackfn, thisArg, value, k, witness.GetStable()); if (ToBoolean(result)) { @@ -29,8 +29,8 @@ namespace typed_array_findindex { // https://tc39.github.io/ecma262/#sec-%typedarray%.prototype.findIndex transitioning javascript builtin - TypedArrayPrototypeFindIndex(js-implicit context: Context, receiver: Object)( - ...arguments): Object { + TypedArrayPrototypeFindIndex(js-implicit context: Context, receiver: JSAny)( + ...arguments): JSAny { // arguments[0] = callback // arguments[1] = thisArg. try { diff --git a/deps/v8/src/builtins/typed-array-foreach.tq b/deps/v8/src/builtins/typed-array-foreach.tq index 656a22e07d..b1ad894122 100644 --- a/deps/v8/src/builtins/typed-array-foreach.tq +++ b/deps/v8/src/builtins/typed-array-foreach.tq @@ -9,7 +9,7 @@ namespace typed_array_foreach { transitioning macro ForEachAllElements(implicit context: Context)( array: typed_array::AttachedJSTypedArray, callbackfn: Callable, - thisArg: Object): Object { + thisArg: JSAny): Undefined { let witness = typed_array::NewAttachedJSTypedArrayWitness(array); // TODO(v8:4153): Support huge TypedArrays here. const length = @@ -17,7 +17,7 @@ namespace typed_array_foreach { 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 value: JSAny = witness.Load(k); Call(context, callbackfn, thisArg, value, k, witness.GetStable()); } return Undefined; @@ -25,8 +25,8 @@ namespace typed_array_foreach { // https://tc39.github.io/ecma262/#sec-%typedarray%.prototype.every transitioning javascript builtin - TypedArrayPrototypeForEach(js-implicit context: Context, receiver: Object)( - ...arguments): Object { + TypedArrayPrototypeForEach(js-implicit context: Context, receiver: JSAny)( + ...arguments): Undefined { // arguments[0] = callback // arguments[1] = this_arg. diff --git a/deps/v8/src/builtins/typed-array-reduce.tq b/deps/v8/src/builtins/typed-array-reduce.tq index d69dc9a98d..7f8eeb7de5 100644 --- a/deps/v8/src/builtins/typed-array-reduce.tq +++ b/deps/v8/src/builtins/typed-array-reduce.tq @@ -9,7 +9,7 @@ namespace typed_array_reduce { transitioning macro ReduceAllElements(implicit context: Context)( array: typed_array::AttachedJSTypedArray, callbackfn: Callable, - initialValue: Object): Object { + initialValue: JSAny | TheHole): JSAny { let witness = typed_array::NewAttachedJSTypedArrayWitness(array); // TODO(v8:4153): Support huge TypedArrays here. const length = @@ -18,25 +18,32 @@ namespace typed_array_reduce { 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); - if (accumulator == TheHole) { - accumulator = value; - } else { - accumulator = Call( - context, callbackfn, Undefined, accumulator, value, k, - witness.GetStable()); + const value: JSAny = witness.Load(k); + typeswitch (accumulator) { + case (TheHole): { + accumulator = value; + } + case (accumulatorNotHole: JSAny): { + accumulator = Call( + context, callbackfn, Undefined, accumulatorNotHole, value, k, + witness.GetStable()); + } } } - if (accumulator == TheHole) { - ThrowTypeError(kReduceNoInitial, kBuiltinName); + typeswitch (accumulator) { + case (TheHole): { + ThrowTypeError(kReduceNoInitial, kBuiltinName); + } + case (accumulator: JSAny): { + return accumulator; + } } - return accumulator; } // https://tc39.github.io/ecma262/#sec-%typedarray%.prototype.reduce transitioning javascript builtin - TypedArrayPrototypeReduce(js-implicit context: Context, receiver: Object)( - ...arguments): Object { + TypedArrayPrototypeReduce(js-implicit context: Context, receiver: JSAny)( + ...arguments): JSAny { // arguments[0] = callback // arguments[1] = initialValue. try { diff --git a/deps/v8/src/builtins/typed-array-reduceright.tq b/deps/v8/src/builtins/typed-array-reduceright.tq index 99a84401ed..c8e4fe83d3 100644 --- a/deps/v8/src/builtins/typed-array-reduceright.tq +++ b/deps/v8/src/builtins/typed-array-reduceright.tq @@ -9,7 +9,7 @@ namespace typed_array_reduceright { transitioning macro ReduceRightAllElements(implicit context: Context)( array: typed_array::AttachedJSTypedArray, callbackfn: Callable, - initialValue: Object): Object { + initialValue: JSAny | TheHole): JSAny { let witness = typed_array::NewAttachedJSTypedArrayWitness(array); // TODO(v8:4153): Support huge TypedArrays here. const length = @@ -18,25 +18,32 @@ namespace typed_array_reduceright { for (let k: Smi = length - 1; k >= 0; k--) { // BUG(4895): We should throw on detached buffers rather than simply exit. witness.Recheck() otherwise break; - const value: Object = witness.Load(k); - if (accumulator == TheHole) { - accumulator = value; - } else { - accumulator = Call( - context, callbackfn, Undefined, accumulator, value, k, - witness.GetStable()); + const value: JSAny = witness.Load(k); + typeswitch (accumulator) { + case (TheHole): { + accumulator = value; + } + case (accumulatorNotHole: JSAny): { + accumulator = Call( + context, callbackfn, Undefined, accumulatorNotHole, value, k, + witness.GetStable()); + } } } - if (accumulator == TheHole) { - ThrowTypeError(kReduceNoInitial, kBuiltinName); + typeswitch (accumulator) { + case (TheHole): { + ThrowTypeError(kReduceNoInitial, kBuiltinName); + } + case (accumulator: JSAny): { + return accumulator; + } } - return accumulator; } // https://tc39.github.io/ecma262/#sec-%typedarray%.prototype.reduceright transitioning javascript builtin - TypedArrayPrototypeReduceRight( - js-implicit context: Context, receiver: Object)(...arguments): Object { + TypedArrayPrototypeReduceRight(js-implicit context: Context, receiver: JSAny)( + ...arguments): JSAny { // arguments[0] = callback // arguments[1] = initialValue. try { diff --git a/deps/v8/src/builtins/typed-array-slice.tq b/deps/v8/src/builtins/typed-array-slice.tq index c0087ae1be..dc13865590 100644 --- a/deps/v8/src/builtins/typed-array-slice.tq +++ b/deps/v8/src/builtins/typed-array-slice.tq @@ -13,7 +13,7 @@ namespace typed_array_slice { macro FastCopy( src: typed_array::AttachedJSTypedArray, dest: JSTypedArray, k: intptr, count: PositiveSmi) labels IfSlow { - GotoIfForceSlowPath() otherwise IfSlow; + if (IsForceSlowPath()) goto IfSlow; const srcKind: ElementsKind = src.elements_kind; const destInfo = typed_array::GetTypedArrayElementsInfo(dest); @@ -53,7 +53,7 @@ namespace typed_array_slice { // https://tc39.github.io/ecma262/#sec-%typedarray%.prototype.slice transitioning javascript builtin TypedArrayPrototypeSlice( - js-implicit context: Context, receiver: Object)(...arguments): Object { + js-implicit context: Context, receiver: JSAny)(...arguments): JSAny { // arguments[0] = start // arguments[1] = end diff --git a/deps/v8/src/builtins/typed-array-some.tq b/deps/v8/src/builtins/typed-array-some.tq index 7056650fba..7d08b1433b 100644 --- a/deps/v8/src/builtins/typed-array-some.tq +++ b/deps/v8/src/builtins/typed-array-some.tq @@ -9,7 +9,7 @@ namespace typed_array_some { transitioning macro SomeAllElements(implicit context: Context)( array: typed_array::AttachedJSTypedArray, callbackfn: Callable, - thisArg: Object): Boolean { + thisArg: JSAny): Boolean { let witness = typed_array::NewAttachedJSTypedArrayWitness(array); // TODO(v8:4153): Support huge TypedArrays here. const length = @@ -17,7 +17,7 @@ namespace typed_array_some { 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 value: JSAny = witness.Load(k); const result = Call(context, callbackfn, thisArg, value, k, witness.GetStable()); if (ToBoolean(result)) { @@ -29,8 +29,8 @@ namespace typed_array_some { // https://tc39.github.io/ecma262/#sec-%typedarray%.prototype.some transitioning javascript builtin - TypedArrayPrototypeSome(js-implicit context: Context, receiver: Object)( - ...arguments): Object { + TypedArrayPrototypeSome(js-implicit context: Context, receiver: JSAny)( + ...arguments): JSAny { // arguments[0] = callback // arguments[1] = thisArg. try { diff --git a/deps/v8/src/builtins/typed-array-subarray.tq b/deps/v8/src/builtins/typed-array-subarray.tq index 4f98123f82..589e67230c 100644 --- a/deps/v8/src/builtins/typed-array-subarray.tq +++ b/deps/v8/src/builtins/typed-array-subarray.tq @@ -6,7 +6,7 @@ namespace typed_array_subarray { // ES %TypedArray%.prototype.subarray transitioning javascript builtin TypedArrayPrototypeSubArray( js-implicit context: Context, - receiver: Object)(...arguments): JSTypedArray { + receiver: JSAny)(...arguments): JSTypedArray { const methodName: constexpr string = '%TypedArray%.prototype.subarray'; // 1. Let O be the this value. diff --git a/deps/v8/src/builtins/typed-array.tq b/deps/v8/src/builtins/typed-array.tq index d03c1a0be9..59100736a5 100644 --- a/deps/v8/src/builtins/typed-array.tq +++ b/deps/v8/src/builtins/typed-array.tq @@ -51,9 +51,9 @@ namespace typed_array { sizeLog2: uintptr; kind: ElementsKind; } - extern runtime TypedArraySortFast(Context, Object): JSTypedArray; + extern runtime TypedArraySortFast(Context, JSAny): JSTypedArray; extern macro TypedArrayBuiltinsAssembler::ValidateTypedArray( - Context, Object, constexpr string): JSTypedArray; + Context, JSAny, constexpr string): JSTypedArray; extern macro TypedArrayBuiltinsAssembler::CallCMemcpy( RawPtr, RawPtr, uintptr): void; @@ -72,10 +72,10 @@ namespace typed_array { extern macro LoadFixedTypedArrayElementAsTagged( RawPtr, Smi, constexpr ElementsKind): Numeric; extern macro StoreJSTypedArrayElementFromTagged( - Context, JSTypedArray, Smi, Object, constexpr ElementsKind); + Context, JSTypedArray, Smi, JSAny, constexpr ElementsKind); - type LoadFn = builtin(Context, JSTypedArray, Smi) => Object; - type StoreFn = builtin(Context, JSTypedArray, Smi, Object) => Object; + type LoadFn = builtin(Context, JSTypedArray, Smi) => JSAny; + type StoreFn = builtin(Context, JSTypedArray, Smi, JSAny) => JSAny; // AttachedJSTypedArray guards that the array's buffer is not detached. transient type AttachedJSTypedArray extends JSTypedArray; @@ -100,7 +100,7 @@ namespace typed_array { this.unstable = %RawDownCast<AttachedJSTypedArray>(this.stable); } - Load(implicit context: Context)(k: Smi): Object { + Load(implicit context: Context)(k: Smi): JSAny { const lf: LoadFn = this.loadfn; return lf(context, this.unstable, k); } @@ -190,14 +190,14 @@ namespace typed_array { } builtin LoadFixedElement<T: type>( - _context: Context, array: JSTypedArray, index: Smi): Object { + _context: Context, array: JSTypedArray, index: Smi): JSAny { return LoadFixedTypedArrayElementAsTagged( array.data_ptr, index, KindForArrayType<T>()); } builtin StoreFixedElement<T: type>( context: Context, typedArray: JSTypedArray, index: Smi, - value: Object): Object { + value: JSAny): JSAny { StoreJSTypedArrayElementFromTagged( context, typedArray, index, value, KindForArrayType<T>()); return Undefined; @@ -205,7 +205,7 @@ namespace typed_array { transitioning macro CallCompare( implicit context: Context, array: JSTypedArray, - comparefn: Callable)(a: Object, b: Object): Number { + comparefn: Callable)(a: JSAny, b: JSAny): Number { // a. Let v be ? ToNumber(? Call(comparefn, undefined, x, y)). const v: Number = ToNumber_Inline(context, Call(context, comparefn, Undefined, a, b)); @@ -238,8 +238,8 @@ namespace typed_array { target.objects[targetIndex] = source.objects[left++]; } else if (left < middle) { // If both have elements, we need to compare. - const leftElement: Object = source.objects[left]; - const rightElement: Object = source.objects[right]; + const leftElement = UnsafeCast<JSAny>(source.objects[left]); + const rightElement = UnsafeCast<JSAny>(source.objects[right]); if (CallCompare(leftElement, rightElement) <= 0) { target.objects[targetIndex] = leftElement; left++; @@ -259,7 +259,7 @@ namespace typed_array { transitioning builtin TypedArrayMergeSort( implicit context: Context, array: JSTypedArray, comparefn: Callable)( - source: FixedArray, from: Smi, to: Smi, target: FixedArray): Object { + source: FixedArray, from: Smi, to: Smi, target: FixedArray): JSAny { assert(to - from > 1); const middle: Smi = from + ((to - from) >> 1); @@ -277,17 +277,16 @@ namespace typed_array { // https://tc39.github.io/ecma262/#sec-%typedarray%.prototype.sort transitioning javascript builtin TypedArrayPrototypeSort( js-implicit context: Context, - receiver: Object)(...arguments): JSTypedArray { + receiver: JSAny)(...arguments): JSTypedArray { // 1. If comparefn is not undefined and IsCallable(comparefn) is false, // throw a TypeError exception. - const comparefnObj: Object = - arguments.length > 0 ? arguments[0] : Undefined; + const comparefnObj: JSAny = arguments.length > 0 ? arguments[0] : Undefined; if (comparefnObj != Undefined && !TaggedIsCallable(comparefnObj)) { ThrowTypeError(kBadSortComparisonFunction, comparefnObj); } // 2. Let obj be the this value. - const obj: Object = receiver; + const obj: JSAny = receiver; // 3. Let buffer be ? ValidateTypedArray(obj). // ValidateTypedArray currently returns the array, not the ViewBuffer. @@ -363,7 +362,7 @@ namespace typed_array { const work2: FixedArray = AllocateZeroedFixedArray(Convert<intptr>(len)); for (let i: Smi = 0; i < len; ++i) { - const element: Object = loadfn(context, array, i); + const element: JSAny = loadfn(context, array, i); work1.objects[i] = element; work2.objects[i] = element; } @@ -372,7 +371,7 @@ namespace typed_array { // work1 contains the sorted numbers. Write them back. for (let i: Smi = 0; i < len; ++i) - storefn(context, array, i, work1.objects[i]); + storefn(context, array, i, UnsafeCast<JSAny>(work1.objects[i])); return array; } diff --git a/deps/v8/src/builtins/x64/builtins-x64.cc b/deps/v8/src/builtins/x64/builtins-x64.cc index f15c8ba29f..b6b407fb33 100644 --- a/deps/v8/src/builtins/x64/builtins-x64.cc +++ b/deps/v8/src/builtins/x64/builtins-x64.cc @@ -64,6 +64,18 @@ static void GenerateTailCallToReturnedCode(MacroAssembler* masm, namespace { +Operand RealStackLimitAsOperand(MacroAssembler* masm) { + DCHECK(masm->root_array_available()); + Isolate* isolate = masm->isolate(); + ExternalReference limit = ExternalReference::address_of_real_jslimit(isolate); + DCHECK(TurboAssembler::IsAddressableThroughRootRegister(isolate, limit)); + + intptr_t offset = + TurboAssembler::RootRegisterOffsetForExternalReference(isolate, limit); + CHECK(is_int32(offset)); + return Operand(kRootRegister, static_cast<int32_t>(offset)); +} + void Generate_StackOverflowCheck( MacroAssembler* masm, Register num_args, Register scratch, Label* stack_overflow, @@ -71,7 +83,7 @@ void Generate_StackOverflowCheck( // 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(kScratchRegister, RealStackLimitAsOperand(masm)); __ movq(scratch, rsp); // Make scratch the space we have left. The stack might already be overflowed // here which will cause scratch to become negative. @@ -735,7 +747,7 @@ void Builtins::Generate_ResumeGeneratorTrampoline(MacroAssembler* masm) { // Check the stack for overflow. We are not trying to catch interruptions // (i.e. debug break and preemption) here, so check the "real stack limit". Label stack_overflow; - __ CompareRoot(rsp, RootIndex::kRealStackLimit); + __ cmpq(rsp, RealStackLimitAsOperand(masm)); __ j(below, &stack_overflow); // Pop return address. @@ -1134,7 +1146,7 @@ void Builtins::Generate_InterpreterEntryTrampoline(MacroAssembler* masm) { Label ok; __ movq(rax, rsp); __ subq(rax, rcx); - __ CompareRoot(rax, RootIndex::kRealStackLimit); + __ cmpq(rax, RealStackLimitAsOperand(masm)); __ j(above_equal, &ok, Label::kNear); __ CallRuntime(Runtime::kThrowStackOverflow); __ bind(&ok); @@ -2339,9 +2351,10 @@ void Generate_PushBoundArguments(MacroAssembler* masm) { __ shlq(rbx, Immediate(kSystemPointerSizeLog2)); __ movq(kScratchRegister, rsp); __ subq(kScratchRegister, rbx); + // We are not trying to catch interruptions (i.e. debug break and // preemption) here, so check the "real stack limit". - __ CompareRoot(kScratchRegister, RootIndex::kRealStackLimit); + __ cmpq(kScratchRegister, RealStackLimitAsOperand(masm)); __ j(above_equal, &done, Label::kNear); { FrameScope scope(masm, StackFrame::MANUAL); @@ -2663,9 +2676,12 @@ void Builtins::Generate_WasmCompileLazy(MacroAssembler* masm) { // Push the function index as second argument. __ Push(r11); // Load the correct CEntry builtin from the instance object. + __ movq(rcx, FieldOperand(kWasmInstanceRegister, + WasmInstanceObject::kIsolateRootOffset)); + auto centry_id = + Builtins::kCEntry_Return1_DontSaveFPRegs_ArgvOnStack_NoBuiltinExit; __ LoadTaggedPointerField( - rcx, FieldOperand(kWasmInstanceRegister, - WasmInstanceObject::kCEntryStubOffset)); + rcx, MemOperand(rcx, IsolateData::builtin_slot_offset(centry_id))); // Initialize the JavaScript context with 0. CEntry will use it to // set the current context on the isolate. __ Move(kContextRegister, Smi::zero()); |