diff --git a/deps/v8/src/builtins/base.tq b/deps/v8/src/builtins/base.tq index 02812274b79e58..3179bc500a3853 100644 --- a/deps/v8/src/builtins/base.tq +++ b/deps/v8/src/builtins/base.tq @@ -1313,7 +1313,6 @@ extern macro ChangeUint32ToWord(uint32): uintptr; // Doesn't sign-extend. extern macro ChangeInt32ToInt64(int32): int64; // Sign-extends. extern macro ChangeUint32ToUint64(uint32): uint64; // Doesn't sign-extend. extern macro LoadNativeContext(Context): NativeContext; -extern macro GetContinuationPreservedEmbedderData(): Object; extern macro TruncateFloat64ToFloat16(float64): float16; extern macro TruncateFloat32ToFloat16(float32): float16; extern macro TruncateFloat64ToFloat32(float64): float32; diff --git a/deps/v8/src/builtins/promise-misc.tq b/deps/v8/src/builtins/promise-misc.tq index b769435d6386bc..1b0611f9b9559e 100644 --- a/deps/v8/src/builtins/promise-misc.tq +++ b/deps/v8/src/builtins/promise-misc.tq @@ -30,6 +30,11 @@ extern macro PromiseBuiltinsAssembler::IsIsolatePromiseHookEnabled(uint32): extern macro PromiseBuiltinsAssembler::PromiseHookFlags(): uint32; +namespace macros { +extern macro GetContinuationPreservedEmbedderData(): Object; +extern macro SetContinuationPreservedEmbedderData(Object): void; +} + namespace promise { extern macro IsFunctionWithPrototypeSlotMap(Map): bool; @@ -80,7 +85,7 @@ macro NewPromiseFulfillReactionJobTask( return new PromiseFulfillReactionJobTask{ map: PromiseFulfillReactionJobTaskMapConstant(), continuation_preserved_embedder_data: - GetContinuationPreservedEmbedderData(), + macros::GetContinuationPreservedEmbedderData(), argument, context: handlerContext, handler, @@ -108,7 +113,7 @@ macro NewPromiseRejectReactionJobTask( return new PromiseRejectReactionJobTask{ map: PromiseRejectReactionJobTaskMapConstant(), continuation_preserved_embedder_data: - GetContinuationPreservedEmbedderData(), + macros::GetContinuationPreservedEmbedderData(), argument, context: handlerContext, handler, @@ -303,7 +308,7 @@ macro NewPromiseReaction( return new PromiseReaction{ map: PromiseReactionMapConstant(), continuation_preserved_embedder_data: - GetContinuationPreservedEmbedderData(), + macros::GetContinuationPreservedEmbedderData(), next: next, reject_handler: rejectHandler, fulfill_handler: fulfillHandler, @@ -347,7 +352,7 @@ macro NewPromiseResolveThenableJobTask( return new PromiseResolveThenableJobTask{ map: PromiseResolveThenableJobTaskMapConstant(), continuation_preserved_embedder_data: - GetContinuationPreservedEmbedderData(), + macros::GetContinuationPreservedEmbedderData(), context: nativeContext, promise_to_resolve: promiseToResolve, thenable, @@ -452,4 +457,18 @@ transitioning macro BranchIfAccessCheckFailed( } } label HasAccess {} } + +@if(V8_ENABLE_CONTINUATION_PRESERVED_EMBEDDER_DATA) +transitioning javascript builtin GetContinuationPreservedEmbedderData( + js-implicit context: Context, receiver: JSAny)(): JSAny { + return UnsafeCast(macros::GetContinuationPreservedEmbedderData()); +} + +@if(V8_ENABLE_CONTINUATION_PRESERVED_EMBEDDER_DATA) +transitioning javascript builtin SetContinuationPreservedEmbedderData( + js-implicit context: Context, receiver: JSAny)(data: Object): Undefined { + macros::SetContinuationPreservedEmbedderData(data); + return Undefined; +} + } diff --git a/deps/v8/src/compiler/js-call-reducer.cc b/deps/v8/src/compiler/js-call-reducer.cc index 5e947298f995f1..768a9e8a112eec 100644 --- a/deps/v8/src/compiler/js-call-reducer.cc +++ b/deps/v8/src/compiler/js-call-reducer.cc @@ -5108,6 +5108,12 @@ Reduction JSCallReducer::ReduceJSCall(Node* node, case Builtin::kBigIntAsIntN: case Builtin::kBigIntAsUintN: return ReduceBigIntAsN(node, builtin); +#ifdef V8_ENABLE_CONTINUATION_PRESERVED_EMBEDDER_DATA + case Builtin::kGetContinuationPreservedEmbedderData: + return ReduceGetContinuationPreservedEmbedderData(node); + case Builtin::kSetContinuationPreservedEmbedderData: + return ReduceSetContinuationPreservedEmbedderData(node); +#endif // V8_ENABLE_CONTINUATION_PRESERVED_EMBEDDER_DATA default: break; } @@ -8780,6 +8786,39 @@ Reduction JSCallReducer::ReduceJSCallMathMinMaxWithArrayLike(Node* node, return ReplaceWithSubgraph(&a, subgraph); } +#ifdef V8_ENABLE_CONTINUATION_PRESERVED_EMBEDDER_DATA +Reduction JSCallReducer::ReduceGetContinuationPreservedEmbedderData( + Node* node) { + JSCallNode n(node); + Effect effect = n.effect(); + Control control = n.control(); + + Node* value = effect = graph()->NewNode( + simplified()->GetContinuationPreservedEmbedderData(), effect); + + ReplaceWithValue(node, value, effect, control); + return Replace(node); +} + +Reduction JSCallReducer::ReduceSetContinuationPreservedEmbedderData( + Node* node) { + JSCallNode n(node); + Effect effect = n.effect(); + Control control = n.control(); + + if (n.ArgumentCount() == 0) return NoChange(); + + effect = + graph()->NewNode(simplified()->SetContinuationPreservedEmbedderData(), + n.Argument(0), effect); + + Node* value = jsgraph()->UndefinedConstant(); + + ReplaceWithValue(node, value, effect, control); + return Replace(node); +} +#endif // V8_ENABLE_CONTINUATION_PRESERVED_EMBEDDER_DATA + CompilationDependencies* JSCallReducer::dependencies() const { return broker()->dependencies(); } diff --git a/deps/v8/src/compiler/js-call-reducer.h b/deps/v8/src/compiler/js-call-reducer.h index a8212a03542188..b7697e763f65d4 100644 --- a/deps/v8/src/compiler/js-call-reducer.h +++ b/deps/v8/src/compiler/js-call-reducer.h @@ -239,6 +239,11 @@ class V8_EXPORT_PRIVATE JSCallReducer final : public AdvancedReducer { base::Optional TryReduceJSCallMathMinMaxWithArrayLike(Node* node); Reduction ReduceJSCallMathMinMaxWithArrayLike(Node* node, Builtin builtin); +#ifdef V8_ENABLE_CONTINUATION_PRESERVED_EMBEDDER_DATA + Reduction ReduceGetContinuationPreservedEmbedderData(Node* node); + Reduction ReduceSetContinuationPreservedEmbedderData(Node* node); +#endif // V8_ENABLE_CONTINUATION_PRESERVED_EMBEDDER_DATA + // The pendant to ReplaceWithValue when using GraphAssembler-based reductions. Reduction ReplaceWithSubgraph(JSCallReducerAssembler* gasm, Node* subgraph); std::pair ReleaseEffectAndControlFromAssembler( diff --git a/deps/v8/src/compiler/opcodes.h b/deps/v8/src/compiler/opcodes.h index e7a154bb055a5f..f52fe76fc16919 100644 --- a/deps/v8/src/compiler/opcodes.h +++ b/deps/v8/src/compiler/opcodes.h @@ -429,6 +429,14 @@ #define SIMPLIFIED_SPECULATIVE_NUMBER_UNOP_LIST(V) V(SpeculativeToNumber) +#ifdef V8_ENABLE_CONTINUATION_PRESERVED_EMBEDDER_DATA +#define SIMPLIFIED_CPED_OP_LIST(V) \ + V(GetContinuationPreservedEmbedderData) \ + V(SetContinuationPreservedEmbedderData) +#else +#define SIMPLIFIED_CPED_OP_LIST(V) +#endif // V8_ENABLE_CONTINUATION_PRESERVED_EMBEDDER_DATA + #define SIMPLIFIED_OTHER_OP_LIST(V) \ V(Allocate) \ V(AllocateRaw) \ @@ -534,7 +542,8 @@ V(TransitionElementsKind) \ V(TypeOf) \ V(Unsigned32Divide) \ - V(VerifyType) + V(VerifyType) \ + SIMPLIFIED_CPED_OP_LIST(V) #define SIMPLIFIED_SPECULATIVE_BIGINT_BINOP_LIST(V) \ V(SpeculativeBigIntAdd) \ diff --git a/deps/v8/src/compiler/simplified-lowering.cc b/deps/v8/src/compiler/simplified-lowering.cc index cc8221152a5d55..f1bd6f3630adae 100644 --- a/deps/v8/src/compiler/simplified-lowering.cc +++ b/deps/v8/src/compiler/simplified-lowering.cc @@ -4635,6 +4635,17 @@ class RepresentationSelector { SetOutput(node, LoadRepresentationOf(node->op()).representation()); return; +#ifdef V8_ENABLE_CONTINUATION_PRESERVED_EMBEDDER_DATA + case IrOpcode::kGetContinuationPreservedEmbedderData: + SetOutput(node, MachineRepresentation::kTagged); + return; + + case IrOpcode::kSetContinuationPreservedEmbedderData: + ProcessInput(node, 0, UseInfo::AnyTagged()); + SetOutput(node, MachineRepresentation::kNone); + return; +#endif // V8_ENABLE_CONTINUATION_PRESERVED_EMBEDDER_DATA + default: FATAL( "Representation inference: unsupported opcode %i (%s), node #%i\n.", diff --git a/deps/v8/src/compiler/simplified-operator.cc b/deps/v8/src/compiler/simplified-operator.cc index b4c6019e58f574..5f3fb51fb584f7 100644 --- a/deps/v8/src/compiler/simplified-operator.cc +++ b/deps/v8/src/compiler/simplified-operator.cc @@ -1339,6 +1339,26 @@ struct SimplifiedOperatorGlobalCache final { kSpeculativeToBigIntBigInt64Operator; SpeculativeToBigIntOperator kSpeculativeToBigIntBigIntOperator; + +#ifdef V8_ENABLE_CONTINUATION_PRESERVED_EMBEDDER_DATA + struct GetContinuationPreservedEmbedderDataOperator : public Operator { + GetContinuationPreservedEmbedderDataOperator() + : Operator(IrOpcode::kGetContinuationPreservedEmbedderData, + Operator::kNoThrow | Operator::kNoDeopt | Operator::kNoWrite, + "GetContinuationPreservedEmbedderData", 0, 1, 0, 1, 1, 0) {} + }; + GetContinuationPreservedEmbedderDataOperator + kGetContinuationPreservedEmbedderData; + + struct SetContinuationPreservedEmbedderDataOperator : public Operator { + SetContinuationPreservedEmbedderDataOperator() + : Operator(IrOpcode::kSetContinuationPreservedEmbedderData, + Operator::kNoThrow | Operator::kNoDeopt | Operator::kNoRead, + "SetContinuationPreservedEmbedderData", 1, 1, 0, 0, 1, 0) {} + }; + SetContinuationPreservedEmbedderDataOperator + kSetContinuationPreservedEmbedderData; +#endif // V8_ENABLE_CONTINUATION_PRESERVED_EMBEDDER_DATA }; namespace { @@ -2198,6 +2218,18 @@ const Operator* SimplifiedOperatorBuilder::StoreField( 2, 1, 1, 0, 1, 0, store_access); } +#ifdef V8_ENABLE_CONTINUATION_PRESERVED_EMBEDDER_DATA +const Operator* +SimplifiedOperatorBuilder::GetContinuationPreservedEmbedderData() { + return &cache_.kGetContinuationPreservedEmbedderData; +} + +const Operator* +SimplifiedOperatorBuilder::SetContinuationPreservedEmbedderData() { + return &cache_.kSetContinuationPreservedEmbedderData; +} +#endif // V8_ENABLE_CONTINUATION_PRESERVED_EMBEDDER_DATA + const Operator* SimplifiedOperatorBuilder::LoadMessage() { return zone()->New(IrOpcode::kLoadMessage, Operator::kEliminatable, "LoadMessage", 1, 1, 1, 1, 1, 0); diff --git a/deps/v8/src/compiler/simplified-operator.h b/deps/v8/src/compiler/simplified-operator.h index bf8b43817988c1..1ba4dfd380477b 100644 --- a/deps/v8/src/compiler/simplified-operator.h +++ b/deps/v8/src/compiler/simplified-operator.h @@ -1218,6 +1218,11 @@ class V8_EXPORT_PRIVATE SimplifiedOperatorBuilder final const FastApiCallFunctionVector& c_candidate_functions, FeedbackSource const& feedback, CallDescriptor* descriptor); +#ifdef V8_ENABLE_CONTINUATION_PRESERVED_EMBEDDER_DATA + const Operator* GetContinuationPreservedEmbedderData(); + const Operator* SetContinuationPreservedEmbedderData(); +#endif // V8_ENABLE_CONTINUATION_PRESERVED_EMBEDDER_DATA + private: Zone* zone() const { return zone_; } diff --git a/deps/v8/src/compiler/turboshaft/assembler.h b/deps/v8/src/compiler/turboshaft/assembler.h index 8493aca79ddc89..19b010c55375db 100644 --- a/deps/v8/src/compiler/turboshaft/assembler.h +++ b/deps/v8/src/compiler/turboshaft/assembler.h @@ -3855,6 +3855,16 @@ class TurboshaftAssemblerOpInterface } #endif // V8_ENABLE_WEBASSEMBLY +#ifdef V8_ENABLE_CONTINUATION_PRESERVED_EMBEDDER_DATA + V GetContinuationPreservedEmbedderData() { + return ReduceIfReachableGetContinuationPreservedEmbedderData(); + } + + void SetContinuationPreservedEmbedderData(V data) { + ReduceIfReachableSetContinuationPreservedEmbedderData(data); + } +#endif // V8_ENABLE_CONTINUATION_PRESERVED_EMBEDDER_DATA + template V resolve(const V& v) { return v; diff --git a/deps/v8/src/compiler/turboshaft/graph-builder.cc b/deps/v8/src/compiler/turboshaft/graph-builder.cc index 4703885b5d6649..a749509f2d96f4 100644 --- a/deps/v8/src/compiler/turboshaft/graph-builder.cc +++ b/deps/v8/src/compiler/turboshaft/graph-builder.cc @@ -2263,6 +2263,14 @@ OpIndex GraphBuilder::Process( return OpIndex::Invalid(); } +#ifdef V8_ENABLE_CONTINUATION_PRESERVED_EMBEDDER_DATA + case IrOpcode::kGetContinuationPreservedEmbedderData: + return __ GetContinuationPreservedEmbedderData(); + case IrOpcode::kSetContinuationPreservedEmbedderData: + __ SetContinuationPreservedEmbedderData(Map(node->InputAt(0))); + return OpIndex::Invalid(); +#endif // V8_ENABLE_CONTINUATION_PRESERVED_EMBEDDER_DATA + default: std::cerr << "unsupported node type: " << *node->op() << "\n"; node->Print(std::cerr); diff --git a/deps/v8/src/compiler/turboshaft/machine-lowering-reducer-inl.h b/deps/v8/src/compiler/turboshaft/machine-lowering-reducer-inl.h index 8f37ef00f7edc1..d451bb4af52a2a 100644 --- a/deps/v8/src/compiler/turboshaft/machine-lowering-reducer-inl.h +++ b/deps/v8/src/compiler/turboshaft/machine-lowering-reducer-inl.h @@ -3164,6 +3164,25 @@ class MachineLoweringReducer : public Next { } } +#ifdef V8_ENABLE_CONTINUATION_PRESERVED_EMBEDDER_DATA + V REDUCE(GetContinuationPreservedEmbedderData)() { + return __ Load( + __ ExternalConstant( + ExternalReference::continuation_preserved_embedder_data(isolate_)), + LoadOp::Kind::RawAligned(), MemoryRepresentation::TaggedPointer()); + } + + OpIndex REDUCE(SetContinuationPreservedEmbedderData)(V data) { + __ Store( + __ ExternalConstant( + ExternalReference::continuation_preserved_embedder_data(isolate_)), + data, StoreOp::Kind::RawAligned(), + MemoryRepresentation::TaggedPointer(), + WriteBarrierKind::kNoWriteBarrier); + return OpIndex::Invalid(); + } +#endif // V8_ENABLE_CONTINUATION_PRESERVED_EMBEDDER_DATA + private: V BuildUint32Mod(V left, V right) { Label done(this); diff --git a/deps/v8/src/compiler/turboshaft/maglev-graph-building-phase.cc b/deps/v8/src/compiler/turboshaft/maglev-graph-building-phase.cc index e30cb4c32ed489..379532db613b85 100644 --- a/deps/v8/src/compiler/turboshaft/maglev-graph-building-phase.cc +++ b/deps/v8/src/compiler/turboshaft/maglev-graph-building-phase.cc @@ -994,6 +994,24 @@ class GraphBuilder { return maglev::ProcessResult::kContinue; } +#ifdef V8_ENABLE_CONTINUATION_PRESERVED_EMBEDDER_DATA + maglev::ProcessResult Process( + maglev::GetContinuationPreservedEmbedderData* node, + const maglev::ProcessingState&) { + V data = __ GetContinuationPreservedEmbedderData(); + SetMap(node, data); + return maglev::ProcessResult::kContinue; + } + + maglev::ProcessResult Process( + maglev::SetContinuationPreservedEmbedderData* node, + const maglev::ProcessingState&) { + V data = Map(node->input(0)); + __ SetContinuationPreservedEmbedderData(data); + return maglev::ProcessResult::kContinue; + } +#endif // V8_ENABLE_CONTINUATION_PRESERVED_EMBEDDER_DATA + template maglev::ProcessResult Process(NodeT* node, const maglev::ProcessingState& state) { diff --git a/deps/v8/src/compiler/turboshaft/operations.h b/deps/v8/src/compiler/turboshaft/operations.h index fc1994105b37d5..5eabc6f755bb27 100644 --- a/deps/v8/src/compiler/turboshaft/operations.h +++ b/deps/v8/src/compiler/turboshaft/operations.h @@ -175,10 +175,19 @@ using Variable = SnapshotTable::Key; V(Switch) \ V(Deoptimize) +#ifdef V8_ENABLE_CONTINUATION_PRESERVED_EMBEDDER_DATA +#define TURBOSHAFT_CPED_OPERATION_LIST(V) \ + V(GetContinuationPreservedEmbedderData) \ + V(SetContinuationPreservedEmbedderData) +#else +#define TURBOSHAFT_CPED_OPERATION_LIST(V) +#endif // V8_ENABLE_CONTINUATION_PRESERVED_EMBEDDER_DATA + // These operations should be lowered to Machine operations during // MachineLoweringPhase. #define TURBOSHAFT_SIMPLIFIED_OPERATION_LIST(V) \ TURBOSHAFT_INTL_OPERATION_LIST(V) \ + TURBOSHAFT_CPED_OPERATION_LIST(V) \ V(ArgumentsLength) \ V(BigIntBinop) \ V(BigIntComparison) \ @@ -8115,6 +8124,47 @@ struct SetStackPointerOp : FixedArityOperationT<1, SetStackPointerOp> { #endif // V8_ENABLE_WEBASSEMBLY +#ifdef V8_ENABLE_CONTINUATION_PRESERVED_EMBEDDER_DATA +struct GetContinuationPreservedEmbedderDataOp + : FixedArityOperationT<0, GetContinuationPreservedEmbedderDataOp> { + static constexpr OpEffects effects = OpEffects().CanReadOffHeapMemory(); + + base::Vector outputs_rep() const { + return RepVector(); + } + + base::Vector inputs_rep( + ZoneVector& storage) const { + return {}; + } + + GetContinuationPreservedEmbedderDataOp() : Base() {} + + void Validate(const Graph& graph) const {} + + auto options() const { return std::tuple{}; } +}; + +struct SetContinuationPreservedEmbedderDataOp + : FixedArityOperationT<1, SetContinuationPreservedEmbedderDataOp> { + static constexpr OpEffects effects = OpEffects().CanWriteOffHeapMemory(); + + base::Vector outputs_rep() const { return {}; } + + base::Vector inputs_rep( + ZoneVector& storage) const { + return MaybeRepVector(); + } + + explicit SetContinuationPreservedEmbedderDataOp(V value) + : Base(value) {} + + void Validate(const Graph& graph) const {} + + auto options() const { return std::tuple{}; } +}; +#endif // V8_ENABLE_CONTINUATION_PRESERVED_EMBEDDER_DATA + #define OPERATION_EFFECTS_CASE(Name) Name##Op::EffectsIfStatic(), static constexpr base::Optional kOperationEffectsTable[kNumberOfOpcodes] = { diff --git a/deps/v8/src/compiler/typer.cc b/deps/v8/src/compiler/typer.cc index 9a346d134b9557..50ed2ae265d704 100644 --- a/deps/v8/src/compiler/typer.cc +++ b/deps/v8/src/compiler/typer.cc @@ -1192,6 +1192,16 @@ Type Typer::Visitor::TypeCall(Node* node) { return Type::Any(); } Type Typer::Visitor::TypeFastApiCall(Node* node) { return Type::Any(); } +#ifdef V8_ENABLE_CONTINUATION_PRESERVED_EMBEDDER_DATA +Type Typer::Visitor::TypeGetContinuationPreservedEmbedderData(Node* node) { + return Type::Any(); +} + +Type Typer::Visitor::TypeSetContinuationPreservedEmbedderData(Node* node) { + UNREACHABLE(); +} +#endif // V8_ENABLE_CONTINUATION_PRESERVED_EMBEDDER_DATA + #if V8_ENABLE_WEBASSEMBLY Type Typer::Visitor::TypeJSWasmCall(Node* node) { const JSWasmCallParameters& op_params = JSWasmCallParametersOf(node->op()); diff --git a/deps/v8/src/compiler/verifier.cc b/deps/v8/src/compiler/verifier.cc index e49766be1981c0..e04996d7bd00e8 100644 --- a/deps/v8/src/compiler/verifier.cc +++ b/deps/v8/src/compiler/verifier.cc @@ -1707,6 +1707,19 @@ void Verifier::Visitor::Check(Node* node, const AllNodes& all) { CHECK_GE(value_count, 1); CheckValueInputIs(node, 0, Type::Any()); // receiver break; +#ifdef V8_ENABLE_CONTINUATION_PRESERVED_EMBEDDER_DATA + case IrOpcode::kGetContinuationPreservedEmbedderData: + CHECK_EQ(value_count, 0); + CHECK_EQ(effect_count, 1); + CheckTypeIs(node, Type::Any()); + break; + case IrOpcode::kSetContinuationPreservedEmbedderData: + CHECK_EQ(value_count, 1); + CHECK_EQ(effect_count, 1); + CheckValueInputIs(node, 0, Type::Any()); + CheckNotTyped(node); + break; +#endif // V8_ENABLE_CONTINUATION_PRESERVED_EMBEDDER_DATA case IrOpcode::kSLVerifierHint: // SLVerifierHint is internal to SimplifiedLowering and should never be // seen by the verifier. diff --git a/deps/v8/src/d8/d8.cc b/deps/v8/src/d8/d8.cc index 715ee06c0d075f..7740363d8a355f 100644 --- a/deps/v8/src/d8/d8.cc +++ b/deps/v8/src/d8/d8.cc @@ -2733,6 +2733,20 @@ void Shell::SetTimeout(const v8::FunctionCallbackInfo& info) { PerIsolateData::Get(isolate)->SetTimeout(callback, context); } +#ifdef V8_ENABLE_CONTINUATION_PRESERVED_EMBEDDER_DATA +void Shell::GetContinuationPreservedEmbedderData( + const v8::FunctionCallbackInfo& info) { + info.GetReturnValue().Set( + info.GetIsolate()->GetContinuationPreservedEmbedderData()); +} +#endif // V8_ENABLE_CONTINUATION_PRESERVED_EMBEDDER_DATA + +void Shell::GetExtrasBindingObject( + const v8::FunctionCallbackInfo& info) { + Local context = info.GetIsolate()->GetCurrentContext(); + info.GetReturnValue().Set(context->GetExtrasBindingObject()); +} + void Shell::ReadCodeTypeAndArguments( const v8::FunctionCallbackInfo& info, int index, CodeType* code_type, Local* arguments) { @@ -3547,8 +3561,15 @@ Local Shell::CreateD8Template(Isolate* isolate) { FunctionTemplate::New(isolate, ProfilerTriggerSample)); d8_template->Set(isolate, "profiler", profiler_template); } +#ifdef V8_ENABLE_CONTINUATION_PRESERVED_EMBEDDER_DATA + d8_template->Set( + isolate, "getContinuationPreservedEmbedderDataViaAPIForTesting", + FunctionTemplate::New(isolate, GetContinuationPreservedEmbedderData)); +#endif // V8_ENABLE_CONTINUATION_PRESERVED_EMBEDDER_DATA d8_template->Set(isolate, "terminate", FunctionTemplate::New(isolate, Terminate)); + d8_template->Set(isolate, "getExtrasBindingObject", + FunctionTemplate::New(isolate, GetExtrasBindingObject)); if (!options.omit_quit) { d8_template->Set(isolate, "quit", FunctionTemplate::New(isolate, Quit)); } diff --git a/deps/v8/src/d8/d8.h b/deps/v8/src/d8/d8.h index b1388f129b881d..f8d42f970df5d0 100644 --- a/deps/v8/src/d8/d8.h +++ b/deps/v8/src/d8/d8.h @@ -665,6 +665,15 @@ class Shell : public i::AllStatic { // the "mkdir -p" command. static void MakeDirectory(const v8::FunctionCallbackInfo& info); static void RemoveDirectory(const v8::FunctionCallbackInfo& info); + +#ifdef V8_ENABLE_CONTINUATION_PRESERVED_EMBEDDER_DATA + static void GetContinuationPreservedEmbedderData( + const v8::FunctionCallbackInfo& info); +#endif // V8_ENABLE_CONTINUATION_PRESERVER_EMBEDDER_DATA + + static void GetExtrasBindingObject( + const v8::FunctionCallbackInfo& info); + static MaybeLocal HostImportModuleDynamically( Local context, Local host_defined_options, Local resource_name, Local specifier, diff --git a/deps/v8/src/debug/debug-evaluate.cc b/deps/v8/src/debug/debug-evaluate.cc index 8e0acf3b817945..1fa6a8e1cd8ebc 100644 --- a/deps/v8/src/debug/debug-evaluate.cc +++ b/deps/v8/src/debug/debug-evaluate.cc @@ -866,6 +866,9 @@ DebugInfo::SideEffectState BuiltinGetSideEffectState(Builtin id) { case Builtin::kConstructWithArrayLike: case Builtin::kGetOwnPropertyDescriptor: case Builtin::kOrdinaryGetOwnPropertyDescriptor: +#ifdef V8_ENABLE_CONTINUATION_PRESERVED_EMBEDDER_DATA + case Builtin::kGetContinuationPreservedEmbedderData: +#endif // V8_ENABLE_CONTINUATION_PRESERVED_EMBEDDER_DATA return DebugInfo::kHasNoSideEffect; #ifdef V8_INTL_SUPPORT diff --git a/deps/v8/src/init/bootstrapper.cc b/deps/v8/src/init/bootstrapper.cc index 647f38943a600e..0d5b3ec7e9a455 100644 --- a/deps/v8/src/init/bootstrapper.cc +++ b/deps/v8/src/init/bootstrapper.cc @@ -6383,6 +6383,18 @@ bool Genesis::InstallExtrasBindings() { SimpleInstallFunction(isolate(), extras_binding, "trace", Builtin::kTrace, 5, true); +#ifdef V8_ENABLE_CONTINUATION_PRESERVED_EMBEDDER_DATA + // binding.getContinuationPreservedEmbedderData() + SimpleInstallFunction( + isolate(), extras_binding, "getContinuationPreservedEmbedderData", + Builtin::kGetContinuationPreservedEmbedderData, 0, true); + + // binding.setContinuationPreservedEmbedderData(value) + SimpleInstallFunction( + isolate(), extras_binding, "setContinuationPreservedEmbedderData", + Builtin::kSetContinuationPreservedEmbedderData, 1, true); +#endif // V8_ENABLE_CONTINUATION_PRESERVED_EMBEDDER_DATA + InitializeConsole(extras_binding); native_context()->set_extras_binding_object(*extras_binding); diff --git a/deps/v8/src/maglev/maglev-graph-builder.cc b/deps/v8/src/maglev/maglev-graph-builder.cc index efcdd6d2028a5e..3b99a44a04e1dc 100644 --- a/deps/v8/src/maglev/maglev-graph-builder.cc +++ b/deps/v8/src/maglev/maglev-graph-builder.cc @@ -6525,6 +6525,21 @@ ReduceResult MaglevGraphBuilder::TryReduceStringPrototypeLocaleCompare( #endif } +#ifdef V8_ENABLE_CONTINUATION_PRESERVED_EMBEDDER_DATA +ReduceResult MaglevGraphBuilder::TryReduceGetContinuationPreservedEmbedderData( + compiler::JSFunctionRef target, CallArguments& args) { + return AddNewNode({}); +} + +ReduceResult MaglevGraphBuilder::TryReduceSetContinuationPreservedEmbedderData( + compiler::JSFunctionRef target, CallArguments& args) { + if (args.count() == 0) return ReduceResult::Fail(); + + AddNewNode({GetTaggedValue(args[0])}); + return GetRootConstant(RootIndex::kUndefinedValue); +} +#endif // V8_ENABLE_CONTINUATION_PRESERVED_EMBEDDER_DATA + template ReduceResult MaglevGraphBuilder::TryBuildLoadDataView(const CallArguments& args, ExternalArrayType type) { diff --git a/deps/v8/src/maglev/maglev-graph-builder.h b/deps/v8/src/maglev/maglev-graph-builder.h index bf242495aa4c82..e997e2f6ff846f 100644 --- a/deps/v8/src/maglev/maglev-graph-builder.h +++ b/deps/v8/src/maglev/maglev-graph-builder.h @@ -1690,31 +1690,40 @@ class MaglevGraphBuilder { ExternalArrayType type, Function&& getValue); -#define MAGLEV_REDUCED_BUILTIN(V) \ - V(ArrayForEach) \ - V(ArrayIsArray) \ - V(DataViewPrototypeGetInt8) \ - V(DataViewPrototypeSetInt8) \ - V(DataViewPrototypeGetInt16) \ - V(DataViewPrototypeSetInt16) \ - V(DataViewPrototypeGetInt32) \ - V(DataViewPrototypeSetInt32) \ - V(DataViewPrototypeGetFloat64) \ - V(DataViewPrototypeSetFloat64) \ - V(FunctionPrototypeCall) \ - V(FunctionPrototypeHasInstance) \ - V(ObjectPrototypeHasOwnProperty) \ - V(MathCeil) \ - V(MathFloor) \ - V(MathPow) \ - V(ArrayPrototypePush) \ - V(ArrayPrototypePop) \ - V(MathRound) \ - V(StringConstructor) \ - V(StringFromCharCode) \ - V(StringPrototypeCharCodeAt) \ - V(StringPrototypeCodePointAt) \ - V(StringPrototypeLocaleCompare) \ +#ifdef V8_ENABLE_CONTINUATION_PRESERVED_EMBEDDER_DATA +#define CONTINUATION_PRESERVED_EMBEDDER_DATA_LIST(V) \ + V(GetContinuationPreservedEmbedderData) \ + V(SetContinuationPreservedEmbedderData) +#else +#define CONTINUATION_PRESERVED_EMBEDDER_DATA_LIST(V) +#endif // V8_ENABLE_CONTINUATION_PRESERVED_EMBEDDER_DATA + +#define MAGLEV_REDUCED_BUILTIN(V) \ + V(ArrayForEach) \ + V(ArrayIsArray) \ + V(DataViewPrototypeGetInt8) \ + V(DataViewPrototypeSetInt8) \ + V(DataViewPrototypeGetInt16) \ + V(DataViewPrototypeSetInt16) \ + V(DataViewPrototypeGetInt32) \ + V(DataViewPrototypeSetInt32) \ + V(DataViewPrototypeGetFloat64) \ + V(DataViewPrototypeSetFloat64) \ + V(FunctionPrototypeCall) \ + V(FunctionPrototypeHasInstance) \ + V(ObjectPrototypeHasOwnProperty) \ + V(MathCeil) \ + V(MathFloor) \ + V(MathPow) \ + V(ArrayPrototypePush) \ + V(ArrayPrototypePop) \ + V(MathRound) \ + V(StringConstructor) \ + V(StringFromCharCode) \ + V(StringPrototypeCharCodeAt) \ + V(StringPrototypeCodePointAt) \ + V(StringPrototypeLocaleCompare) \ + CONTINUATION_PRESERVED_EMBEDDER_DATA_LIST(V) \ IEEE_754_UNARY_LIST(V) #define DEFINE_BUILTIN_REDUCER(Name, ...) \ diff --git a/deps/v8/src/maglev/maglev-ir.cc b/deps/v8/src/maglev/maglev-ir.cc index c2f9bd9fb779d8..c58e86290bd5f3 100644 --- a/deps/v8/src/maglev/maglev-ir.cc +++ b/deps/v8/src/maglev/maglev-ir.cc @@ -5735,6 +5735,36 @@ void CheckTypedArrayNotDetached::GenerateCode(MaglevAssembler* masm, __ DeoptIfBufferDetached(object, scratch, this); } +void GetContinuationPreservedEmbedderData::SetValueLocationConstraints() { + DefineAsRegister(this); +} + +void GetContinuationPreservedEmbedderData::GenerateCode( + MaglevAssembler* masm, const ProcessingState& state) { + Register result = ToRegister(this->result()); + MaglevAssembler::ScratchRegisterScope temps(masm); + Register scratch = temps.GetDefaultScratchRegister(); + MemOperand reference = __ ExternalReferenceAsOperand( + ExternalReference::continuation_preserved_embedder_data(masm->isolate()), + scratch); + __ Move(result, reference); +} + +void SetContinuationPreservedEmbedderData::SetValueLocationConstraints() { + UseRegister(data_input()); +} + +void SetContinuationPreservedEmbedderData::GenerateCode( + MaglevAssembler* masm, const ProcessingState& state) { + Register data = ToRegister(data_input()); + MaglevAssembler::ScratchRegisterScope temps(masm); + Register scratch = temps.GetDefaultScratchRegister(); + MemOperand reference = __ ExternalReferenceAsOperand( + ExternalReference::continuation_preserved_embedder_data(masm->isolate()), + scratch); + __ Move(reference, data); +} + namespace { template diff --git a/deps/v8/src/maglev/maglev-ir.h b/deps/v8/src/maglev/maglev-ir.h index f66f5b50ec06a5..4c8882be60bdc7 100644 --- a/deps/v8/src/maglev/maglev-ir.h +++ b/deps/v8/src/maglev/maglev-ir.h @@ -261,6 +261,7 @@ class MergePointInterpreterFrameState; V(ToString) \ V(NumberToString) \ V(UpdateJSArrayLength) \ + V(GetContinuationPreservedEmbedderData) \ CONSTANT_VALUE_NODE_LIST(V) \ INT32_OPERATIONS_NODE_LIST(V) \ FLOAT64_OPERATIONS_NODE_LIST(V) \ @@ -324,6 +325,7 @@ class MergePointInterpreterFrameState; V(ThrowIfNotSuperConstructor) \ V(TransitionElementsKind) \ V(TransitionElementsKindOrCheckMap) \ + V(SetContinuationPreservedEmbedderData) \ GAP_MOVE_NODE_LIST(V) \ VALUE_NODE_LIST(V) @@ -8729,6 +8731,42 @@ class TransitionElementsKindOrCheckMap const compiler::MapRef transition_target_; }; +class GetContinuationPreservedEmbedderData + : public FixedInputValueNodeT<0, GetContinuationPreservedEmbedderData> { + using Base = FixedInputValueNodeT<0, GetContinuationPreservedEmbedderData>; + + public: + explicit GetContinuationPreservedEmbedderData(uint64_t bitfield) + : Base(bitfield) {} + + void SetValueLocationConstraints(); + void GenerateCode(MaglevAssembler*, const ProcessingState&); + void PrintParams(std::ostream&, MaglevGraphLabeller*) const {} + + static constexpr OpProperties kProperties = + OpProperties::CanRead() | OpProperties::TaggedValue(); +}; + +class SetContinuationPreservedEmbedderData + : public FixedInputNodeT<1, SetContinuationPreservedEmbedderData> { + using Base = FixedInputNodeT<1, SetContinuationPreservedEmbedderData>; + + public: + explicit SetContinuationPreservedEmbedderData(uint64_t bitfield) + : Base(bitfield) {} + + static constexpr + typename Base::InputTypes kInputTypes{ValueRepresentation::kTagged}; + + Input& data_input() { return input(0); } + + void SetValueLocationConstraints(); + void GenerateCode(MaglevAssembler*, const ProcessingState&); + void PrintParams(std::ostream&, MaglevGraphLabeller*) const {} + + static constexpr OpProperties kProperties = OpProperties::CanWrite(); +}; + class ControlNode : public NodeBase { public: // A "hole" in control flow is a control node that unconditionally interrupts diff --git a/deps/v8/src/torque/torque-parser.cc b/deps/v8/src/torque/torque-parser.cc index b47a1110b5e465..ad8fa0986dbf9f 100644 --- a/deps/v8/src/torque/torque-parser.cc +++ b/deps/v8/src/torque/torque-parser.cc @@ -670,36 +670,6 @@ base::Optional MakeTorqueMacroDeclaration( return ParseResult{result}; } -base::Optional MakeTorqueBuiltinDeclaration( - ParseResultIterator* child_results) { - const bool has_custom_interface_descriptor = HasAnnotation( - child_results, ANNOTATION_CUSTOM_INTERFACE_DESCRIPTOR, "builtin"); - auto transitioning = child_results->NextAs(); - auto javascript_linkage = child_results->NextAs(); - auto name = child_results->NextAs(); - if (!IsUpperCamelCase(name->value)) { - NamingConventionError("Builtin", name, "UpperCamelCase"); - } - - auto generic_parameters = child_results->NextAs(); - LintGenericParameters(generic_parameters); - - auto args = child_results->NextAs(); - auto return_type = child_results->NextAs(); - auto body = child_results->NextAs>(); - CallableDeclaration* declaration = MakeNode( - transitioning, javascript_linkage, name, args, return_type, - has_custom_interface_descriptor, body); - Declaration* result = declaration; - if (generic_parameters.empty()) { - if (!body) ReportError("A non-generic declaration needs a body."); - } else { - result = - MakeNode(generic_parameters, declaration); - } - return ParseResult{result}; -} - base::Optional MakeConstDeclaration( ParseResultIterator* child_results) { auto name = child_results->NextAs(); @@ -961,6 +931,46 @@ int GetAnnotationValue(const AnnotationSet& annotations, const char* name, return opt_value.has_value() ? *opt_value : default_value; } +base::Optional MakeTorqueBuiltinDeclaration( + ParseResultIterator* child_results) { + AnnotationSet annotations( + child_results, {ANNOTATION_CUSTOM_INTERFACE_DESCRIPTOR}, {ANNOTATION_IF}); + const bool has_custom_interface_descriptor = + annotations.Contains(ANNOTATION_CUSTOM_INTERFACE_DESCRIPTOR); + auto transitioning = child_results->NextAs(); + auto javascript_linkage = child_results->NextAs(); + auto name = child_results->NextAs(); + if (!IsUpperCamelCase(name->value)) { + NamingConventionError("Builtin", name, "UpperCamelCase"); + } + + auto generic_parameters = child_results->NextAs(); + LintGenericParameters(generic_parameters); + + auto args = child_results->NextAs(); + auto return_type = child_results->NextAs(); + auto body = child_results->NextAs>(); + CallableDeclaration* declaration = MakeNode( + transitioning, javascript_linkage, name, args, return_type, + has_custom_interface_descriptor, body); + Declaration* result = declaration; + if (generic_parameters.empty()) { + if (!body) ReportError("A non-generic declaration needs a body."); + } else { + result = + MakeNode(generic_parameters, declaration); + } + std::vector results; + if (base::Optional condition = + annotations.GetStringParam(ANNOTATION_IF)) { + if (!BuildFlags::GetFlag(*condition, ANNOTATION_IF)) { + return ParseResult{std::move(results)}; + } + } + results.push_back(result); + return ParseResult{std::move(results)}; +} + InstanceTypeConstraints MakeInstanceTypeConstraints( const AnnotationSet& annotations) { InstanceTypeConstraints result; @@ -2863,7 +2873,7 @@ struct TorqueGrammar : Grammar { CheckIf(Token("javascript")), Token("builtin"), &name, TryOrDefault(&genericParameters), ¶meterListAllowVararg, &returnType, &optionalBody}, - AsSingletonVector()), + MakeTorqueBuiltinDeclaration), Rule({CheckIf(Token("transitioning")), &name, &genericSpecializationTypeList, ¶meterListAllowVararg, &returnType, optionalLabelList, &block}, diff --git a/deps/v8/test/mjsunit/extras-cped.js b/deps/v8/test/mjsunit/extras-cped.js new file mode 100644 index 00000000000000..acbffa8a9b37e2 --- /dev/null +++ b/deps/v8/test/mjsunit/extras-cped.js @@ -0,0 +1,85 @@ +// Copyright 2024 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. + +// Flags: --allow-natives-syntax + +const { + getContinuationPreservedEmbedderData, + setContinuationPreservedEmbedderData, +} = d8.getExtrasBindingObject(); + + +// Basic set and get +const foo = { bar: 'baz' }; +setContinuationPreservedEmbedderData(foo); +assertEquals(foo, getContinuationPreservedEmbedderData()); + +// Captures at the point a continuation is created +{ + // Resolve path + setContinuationPreservedEmbedderData('init'); + let resolve; + const p = new Promise(r => { + resolve = r; + }); + + setContinuationPreservedEmbedderData('resolve'); + resolve(); + + setContinuationPreservedEmbedderData('continuation-created'); + p.then(deferredVerify('continuation-created')); + setContinuationPreservedEmbedderData('after'); + %PerformMicrotaskCheckpoint(); +} +{ + // Reject path + setContinuationPreservedEmbedderData('init'); + let reject; + const p = new Promise((_, r) => { + reject = r; + }); + + setContinuationPreservedEmbedderData('resolve'); + reject(); + + setContinuationPreservedEmbedderData('continuation-created'); + p.catch(deferredVerify('continuation-created')); + setContinuationPreservedEmbedderData('after'); + %PerformMicrotaskCheckpoint(); +} + +// Should propagate through thenables +function thenable(expected) { + const verify = deferredVerify(expected); + return { + then(fulfill) { + verify(); + fulfill(); + } + } +} + +async function testThenables() { + setContinuationPreservedEmbedderData('plain thenable'); + await thenable('plain thenable'); + + setContinuationPreservedEmbedderData('resolved thenable'); + await Promise.resolve(thenable('resolved thenable')); + + setContinuationPreservedEmbedderData('async returned thenable'); + await (async () => thenable('async returned thenable'))(); +} + +testThenables(); + +%PerformMicrotaskCheckpoint(); + +// +// Test helpers +// +function deferredVerify(expected) { + return () => { + assertEquals(expected, getContinuationPreservedEmbedderData()); + }; +} diff --git a/deps/v8/test/mjsunit/maglev/extras-cped.js b/deps/v8/test/mjsunit/maglev/extras-cped.js new file mode 100644 index 00000000000000..7d63c871d88b1a --- /dev/null +++ b/deps/v8/test/mjsunit/maglev/extras-cped.js @@ -0,0 +1,39 @@ +// Copyright 2024 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. + +// Flags: --allow-natives-syntax + +const { + getExtrasBindingObject, + getContinuationPreservedEmbedderDataViaAPIForTesting, +} = d8; +const { + getContinuationPreservedEmbedderData, + setContinuationPreservedEmbedderData, +} = getExtrasBindingObject(); + +function testOpt(v) { + setContinuationPreservedEmbedderData(v); + return getContinuationPreservedEmbedderData(); +} + +const runTestOpt = (v) => { + const data = testOpt(v); + assertEquals(data, v); + assertEquals(getContinuationPreservedEmbedderDataViaAPIForTesting(), v); +}; + +%PrepareFunctionForOptimization(testOpt); + +runTestOpt(5); +runTestOpt(5.5); +runTestOpt({}); + +%OptimizeMaglevOnNextCall(testOpt); + +runTestOpt(5); +runTestOpt(5.5); +runTestOpt({}); + +assertTrue(isMaglevved(testOpt)); diff --git a/deps/v8/test/mjsunit/mjsunit.status b/deps/v8/test/mjsunit/mjsunit.status index f797279ecaf764..8fed543253c44d 100644 --- a/deps/v8/test/mjsunit/mjsunit.status +++ b/deps/v8/test/mjsunit/mjsunit.status @@ -486,6 +486,9 @@ 'compiler/regress-crbug-1201057': [SKIP], 'compiler/regress-crbug-1201082': [SKIP], + 'maglev/extras-cped': [SKIP], + 'turboshaft/extras-cped': [SKIP], + # These tests check that we can trace the compiler. 'tools/compiler-trace-flags': [SKIP], @@ -1432,6 +1435,9 @@ 'regress/regress-1049982-1': [SKIP], 'regress/regress-1049982-2': [SKIP], + 'maglev/extras-cped': [SKIP], + 'turboshaft/extras-cped': [SKIP], + # Wasm serialization relies on TurboFan to be available, hence does not work # in the 'nooptimization' variant. 'wasm/serialization-with-compilation-hints': [SKIP], @@ -2078,6 +2084,7 @@ # the deprecated map. Wiring this through in Maglev would be too messy to be # worth it. 'regress/regress-map-invalidation-2': [FAIL], + 'turboshaft/extras-cped': [SKIP], }], # variant in (stress_maglev, stress_maglev_future, stress_maglev_no_turbofan, maglev_no_turbofan) ['(variant in (stress_maglev, stress_maglev_future, stress_maglev_no_turbofan, maglev_no_turbofan)) and (arch != arm)', { diff --git a/deps/v8/test/mjsunit/turboshaft/extras-cped.js b/deps/v8/test/mjsunit/turboshaft/extras-cped.js new file mode 100644 index 00000000000000..d0ee141ae2df6a --- /dev/null +++ b/deps/v8/test/mjsunit/turboshaft/extras-cped.js @@ -0,0 +1,39 @@ +// Copyright 2024 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. + +// Flags: --allow-natives-syntax + +const { + getExtrasBindingObject, + getContinuationPreservedEmbedderDataViaAPIForTesting, +} = d8; +const { + getContinuationPreservedEmbedderData, + setContinuationPreservedEmbedderData, +} = getExtrasBindingObject(); + +function testOpt(v) { + setContinuationPreservedEmbedderData(v); + return getContinuationPreservedEmbedderData(); +} + +const runTestOpt = (v) => { + const data = testOpt(v); + assertEquals(data, v); + assertEquals(getContinuationPreservedEmbedderDataViaAPIForTesting(), v); +}; + +%PrepareFunctionForOptimization(testOpt); + +runTestOpt(5); +runTestOpt(5.5); +runTestOpt({}); + +%OptimizeFunctionOnNextCall(testOpt); + +runTestOpt(5); +runTestOpt(5.5); +runTestOpt({}); + +assertTrue(isTurboFanned(testOpt));