diff options
author | Myles Borins <mylesborins@google.com> | 2018-04-10 21:39:51 -0400 |
---|---|---|
committer | Myles Borins <mylesborins@google.com> | 2018-04-11 13:22:42 -0400 |
commit | 12a1b9b8049462e47181a298120243dc83e81c55 (patch) | |
tree | 8605276308c8b4e3597516961266bae1af57557a /deps/v8/src/builtins/builtins-internal-gen.cc | |
parent | 78cd8263354705b767ef8c6a651740efe4931ba0 (diff) | |
download | node-new-12a1b9b8049462e47181a298120243dc83e81c55.tar.gz |
deps: update V8 to 6.6.346.23
PR-URL: https://github.com/nodejs/node/pull/19201
Reviewed-By: Ali Ijaz Sheikh <ofrobots@google.com>
Reviewed-By: Myles Borins <myles.borins@gmail.com>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Diffstat (limited to 'deps/v8/src/builtins/builtins-internal-gen.cc')
-rw-r--r-- | deps/v8/src/builtins/builtins-internal-gen.cc | 359 |
1 files changed, 174 insertions, 185 deletions
diff --git a/deps/v8/src/builtins/builtins-internal-gen.cc b/deps/v8/src/builtins/builtins-internal-gen.cc index bb4b66e3a4..edc529c798 100644 --- a/deps/v8/src/builtins/builtins-internal-gen.cc +++ b/deps/v8/src/builtins/builtins-internal-gen.cc @@ -73,8 +73,8 @@ TF_BUILTIN(GrowFastSmiOrObjectElements, CodeStubAssembler) { TF_BUILTIN(NewArgumentsElements, CodeStubAssembler) { Node* frame = Parameter(Descriptor::kFrame); - Node* length = SmiToWord(Parameter(Descriptor::kLength)); - Node* mapped_count = SmiToWord(Parameter(Descriptor::kMappedCount)); + Node* length = SmiToIntPtr(Parameter(Descriptor::kLength)); + Node* mapped_count = SmiToIntPtr(Parameter(Descriptor::kMappedCount)); // Check if we can allocate in new space. ElementsKind kind = PACKED_ELEMENTS; @@ -164,8 +164,8 @@ TF_BUILTIN(NewArgumentsElements, CodeStubAssembler) { { // Allocate in old space (or large object space). TailCallRuntime(Runtime::kNewArgumentsElements, NoContextConstant(), - BitcastWordToTagged(frame), SmiFromWord(length), - SmiFromWord(mapped_count)); + BitcastWordToTagged(frame), SmiFromIntPtr(length), + SmiFromIntPtr(mapped_count)); } } @@ -202,7 +202,7 @@ class RecordWriteCodeStubAssembler : public CodeStubAssembler { Node* mask; GetMarkBit(object, &cell, &mask); - mask = TruncateWordToWord32(mask); + mask = TruncateIntPtrToInt32(mask); Node* bits = Load(MachineType::Int32(), cell); Node* bit_0 = Word32And(bits, mask); @@ -239,7 +239,7 @@ class RecordWriteCodeStubAssembler : public CodeStubAssembler { Node* cell; Node* mask; GetMarkBit(object, &cell, &mask); - mask = TruncateWordToWord32(mask); + mask = TruncateIntPtrToInt32(mask); // Non-white has 1 for the first bit, so we only need to check for the first // bit. return Word32Equal(Word32And(Load(MachineType::Int32(), cell), mask), @@ -628,6 +628,9 @@ class InternalBuiltinsAssembler : public CodeStubAssembler { void EnterMicrotaskContext(TNode<Context> context); void LeaveMicrotaskContext(); + void RunPromiseHook(Runtime::FunctionId id, TNode<Context> context, + SloppyTNode<HeapObject> payload); + TNode<Object> GetPendingException() { auto ref = ExternalReference(kPendingExceptionAddress, isolate()); return TNode<Object>::UncheckedCast( @@ -745,6 +748,19 @@ void InternalBuiltinsAssembler::LeaveMicrotaskContext() { } } +void InternalBuiltinsAssembler::RunPromiseHook( + Runtime::FunctionId id, TNode<Context> context, + SloppyTNode<HeapObject> payload) { + Label hook(this, Label::kDeferred), done_hook(this); + Branch(IsPromiseHookEnabledOrDebugIsActive(), &hook, &done_hook); + BIND(&hook); + { + CallRuntime(id, context, payload); + Goto(&done_hook); + } + BIND(&done_hook); +} + TF_BUILTIN(EnqueueMicrotask, InternalBuiltinsAssembler) { Node* microtask = Parameter(Descriptor::kMicrotask); @@ -812,13 +828,15 @@ TF_BUILTIN(EnqueueMicrotask, InternalBuiltinsAssembler) { } TF_BUILTIN(RunMicrotasks, InternalBuiltinsAssembler) { - Label init_queue_loop(this); + // Load the current context from the isolate. + TNode<Context> current_context = GetCurrentContext(); + Label init_queue_loop(this); Goto(&init_queue_loop); BIND(&init_queue_loop); { TVARIABLE(IntPtrT, index, IntPtrConstant(0)); - Label loop(this, &index); + Label loop(this, &index), loop_next(this); TNode<IntPtrT> num_tasks = GetPendingMicrotaskCount(); ReturnIf(IntPtrEqual(num_tasks, IntPtrConstant(0)), UndefinedConstant()); @@ -830,222 +848,193 @@ TF_BUILTIN(RunMicrotasks, InternalBuiltinsAssembler) { CSA_ASSERT(this, IntPtrGreaterThan(num_tasks, IntPtrConstant(0))); SetPendingMicrotaskCount(IntPtrConstant(0)); - SetMicrotaskQueue( - TNode<FixedArray>::UncheckedCast(EmptyFixedArrayConstant())); + SetMicrotaskQueue(EmptyFixedArrayConstant()); Goto(&loop); BIND(&loop); { - TNode<HeapObject> microtask = - TNode<HeapObject>::UncheckedCast(LoadFixedArrayElement(queue, index)); - index = IntPtrAdd(index, IntPtrConstant(1)); + TNode<HeapObject> microtask = TNode<HeapObject>::UncheckedCast( + LoadFixedArrayElement(queue, index.value())); + index = IntPtrAdd(index.value(), IntPtrConstant(1)); CSA_ASSERT(this, TaggedIsNotSmi(microtask)); TNode<Map> microtask_map = LoadMap(microtask); TNode<Int32T> microtask_type = LoadMapInstanceType(microtask_map); - Label is_call_handler_info(this); - Label is_function(this); - Label is_promise_resolve_thenable_job(this); - Label is_promise_reaction_job(this); - Label is_unreachable(this); - - int32_t case_values[] = {TUPLE3_TYPE, // CallHandlerInfo - JS_FUNCTION_TYPE, - PROMISE_RESOLVE_THENABLE_JOB_INFO_TYPE, - PROMISE_REACTION_JOB_INFO_TYPE}; - - Label* case_labels[] = {&is_call_handler_info, &is_function, - &is_promise_resolve_thenable_job, - &is_promise_reaction_job}; - + VARIABLE(var_exception, MachineRepresentation::kTagged, + TheHoleConstant()); + Label if_exception(this, Label::kDeferred); + Label is_callable(this), is_callback(this), + is_promise_fulfill_reaction_job(this), + is_promise_reject_reaction_job(this), + is_promise_resolve_thenable_job(this), + is_unreachable(this, Label::kDeferred); + + 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}; + 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)); - BIND(&is_call_handler_info); + BIND(&is_callable); { - // Bailout to C++ slow path for the remainder of the loop. - auto index_ref = - ExternalReference(kMicrotaskQueueBailoutIndexAddress, isolate()); - auto count_ref = - ExternalReference(kMicrotaskQueueBailoutCountAddress, isolate()); - auto rep = kIntSize == 4 ? MachineRepresentation::kWord32 - : MachineRepresentation::kWord64; - - // index was pre-incremented, decrement for bailout to C++. - Node* value = IntPtrSub(index, IntPtrConstant(1)); - - if (kPointerSize == 4) { - DCHECK_EQ(kIntSize, 4); - StoreNoWriteBarrier(rep, ExternalConstant(index_ref), value); - StoreNoWriteBarrier(rep, ExternalConstant(count_ref), num_tasks); - } else { - Node* count = num_tasks; - if (kIntSize == 4) { - value = TruncateInt64ToInt32(value); - count = TruncateInt64ToInt32(count); - } - StoreNoWriteBarrier(rep, ExternalConstant(index_ref), value); - StoreNoWriteBarrier(rep, ExternalConstant(count_ref), count); - } - - Return(queue); - } + // Enter the context of the {microtask}. + TNode<Context> microtask_context = + LoadObjectField<Context>(microtask, CallableTask::kContextOffset); + TNode<Context> native_context = LoadNativeContext(microtask_context); - BIND(&is_function); - { - Label cont(this); - VARIABLE(exception, MachineRepresentation::kTagged, TheHoleConstant()); - TNode<Context> old_context = GetCurrentContext(); - TNode<Context> fn_context = TNode<Context>::UncheckedCast( - LoadObjectField(microtask, JSFunction::kContextOffset)); - TNode<Context> native_context = - TNode<Context>::UncheckedCast(LoadNativeContext(fn_context)); + CSA_ASSERT(this, IsNativeContext(native_context)); + EnterMicrotaskContext(microtask_context); SetCurrentContext(native_context); - EnterMicrotaskContext(fn_context); - Node* const call = CallJS(CodeFactory::Call(isolate()), native_context, - microtask, UndefinedConstant()); - GotoIfException(call, &cont); - Goto(&cont); - BIND(&cont); + + TNode<JSReceiver> callable = LoadObjectField<JSReceiver>( + microtask, CallableTask::kCallableOffset); + Node* const result = CallJS( + CodeFactory::Call(isolate(), ConvertReceiverMode::kNullOrUndefined), + microtask_context, callable, UndefinedConstant()); + GotoIfException(result, &if_exception, &var_exception); LeaveMicrotaskContext(); - SetCurrentContext(old_context); - Branch(IntPtrLessThan(index, num_tasks), &loop, &init_queue_loop); + SetCurrentContext(current_context); + Goto(&loop_next); + } + + BIND(&is_callback); + { + Node* const microtask_callback = + LoadObjectField(microtask, CallbackTask::kCallbackOffset); + Node* const microtask_data = + LoadObjectField(microtask, CallbackTask::kDataOffset); + + // If this turns out to become a bottleneck because of the calls + // to C++ via CEntryStub, we can choose to speed them up using a + // similar mechanism that we use for the CallApiFunction stub, + // except that calling the MicrotaskCallback is even easier, since + // it doesn't accept any tagged parameters, doesn't return a value + // and ignores exceptions. + // + // 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). + CallRuntime(Runtime::kRunMicrotaskCallback, current_context, + microtask_callback, microtask_data); + Goto(&loop_next); } BIND(&is_promise_resolve_thenable_job); { - VARIABLE(exception, MachineRepresentation::kTagged, TheHoleConstant()); - TNode<Context> old_context = GetCurrentContext(); - TNode<Context> microtask_context = - TNode<Context>::UncheckedCast(LoadObjectField( - microtask, PromiseResolveThenableJobInfo::kContextOffset)); - TNode<Context> native_context = - TNode<Context>::UncheckedCast(LoadNativeContext(microtask_context)); + // Enter the context of the {microtask}. + TNode<Context> microtask_context = LoadObjectField<Context>( + microtask, PromiseResolveThenableJobTask::kContextOffset); + TNode<Context> native_context = LoadNativeContext(microtask_context); + CSA_ASSERT(this, IsNativeContext(native_context)); + EnterMicrotaskContext(microtask_context); SetCurrentContext(native_context); + + Node* const promise_to_resolve = LoadObjectField( + microtask, PromiseResolveThenableJobTask::kPromiseToResolveOffset); + Node* const then = LoadObjectField( + microtask, PromiseResolveThenableJobTask::kThenOffset); + Node* const thenable = LoadObjectField( + microtask, PromiseResolveThenableJobTask::kThenableOffset); + + Node* const result = + CallBuiltin(Builtins::kPromiseResolveThenableJob, native_context, + promise_to_resolve, thenable, then); + GotoIfException(result, &if_exception, &var_exception); + LeaveMicrotaskContext(); + SetCurrentContext(current_context); + Goto(&loop_next); + } + + BIND(&is_promise_fulfill_reaction_job); + { + // Enter the context of the {microtask}. + TNode<Context> microtask_context = LoadObjectField<Context>( + microtask, PromiseReactionJobTask::kContextOffset); + TNode<Context> native_context = LoadNativeContext(microtask_context); + CSA_ASSERT(this, IsNativeContext(native_context)); EnterMicrotaskContext(microtask_context); + SetCurrentContext(native_context); - Label if_unhandled_exception(this), done(this); - Node* const ret = CallBuiltin(Builtins::kPromiseResolveThenableJob, - native_context, microtask); - GotoIfException(ret, &if_unhandled_exception, &exception); - Goto(&done); + Node* const argument = + LoadObjectField(microtask, PromiseReactionJobTask::kArgumentOffset); + Node* const handler = + LoadObjectField(microtask, PromiseReactionJobTask::kHandlerOffset); + Node* const payload = + LoadObjectField(microtask, PromiseReactionJobTask::kPayloadOffset); - BIND(&if_unhandled_exception); - CallRuntime(Runtime::kReportMessage, native_context, exception.value()); - Goto(&done); + // Run the promise before/debug hook if enabled. + RunPromiseHook(Runtime::kPromiseHookBefore, microtask_context, payload); - BIND(&done); - LeaveMicrotaskContext(); - SetCurrentContext(old_context); + Node* const result = + CallBuiltin(Builtins::kPromiseFulfillReactionJob, microtask_context, + argument, handler, payload); + GotoIfException(result, &if_exception, &var_exception); + + // Run the promise after/debug hook if enabled. + RunPromiseHook(Runtime::kPromiseHookAfter, microtask_context, payload); - Branch(IntPtrLessThan(index, num_tasks), &loop, &init_queue_loop); + LeaveMicrotaskContext(); + SetCurrentContext(current_context); + Goto(&loop_next); } - BIND(&is_promise_reaction_job); + BIND(&is_promise_reject_reaction_job); { - Label if_multiple(this); - Label if_single(this); - - Node* const value = - LoadObjectField(microtask, PromiseReactionJobInfo::kValueOffset); - Node* const tasks = - LoadObjectField(microtask, PromiseReactionJobInfo::kTasksOffset); - Node* const deferred_promises = LoadObjectField( - microtask, PromiseReactionJobInfo::kDeferredPromiseOffset); - Node* const deferred_on_resolves = LoadObjectField( - microtask, PromiseReactionJobInfo::kDeferredOnResolveOffset); - Node* const deferred_on_rejects = LoadObjectField( - microtask, PromiseReactionJobInfo::kDeferredOnRejectOffset); - - TNode<Context> old_context = GetCurrentContext(); - TNode<Context> microtask_context = TNode<Context>::UncheckedCast( - LoadObjectField(microtask, PromiseReactionJobInfo::kContextOffset)); - TNode<Context> native_context = - TNode<Context>::UncheckedCast(LoadNativeContext(microtask_context)); - SetCurrentContext(native_context); + // Enter the context of the {microtask}. + TNode<Context> microtask_context = LoadObjectField<Context>( + microtask, PromiseReactionJobTask::kContextOffset); + TNode<Context> native_context = LoadNativeContext(microtask_context); + CSA_ASSERT(this, IsNativeContext(native_context)); EnterMicrotaskContext(microtask_context); + SetCurrentContext(native_context); + + Node* const argument = + LoadObjectField(microtask, PromiseReactionJobTask::kArgumentOffset); + Node* const handler = + LoadObjectField(microtask, PromiseReactionJobTask::kHandlerOffset); + Node* const payload = + LoadObjectField(microtask, PromiseReactionJobTask::kPayloadOffset); + + // Run the promise before/debug hook if enabled. + RunPromiseHook(Runtime::kPromiseHookBefore, microtask_context, payload); + + Node* const result = + CallBuiltin(Builtins::kPromiseRejectReactionJob, microtask_context, + argument, handler, payload); + GotoIfException(result, &if_exception, &var_exception); + + // Run the promise after/debug hook if enabled. + RunPromiseHook(Runtime::kPromiseHookAfter, microtask_context, payload); - Branch(IsFixedArray(deferred_promises), &if_multiple, &if_single); - - BIND(&if_single); - { - CallBuiltin(Builtins::kPromiseHandle, native_context, value, tasks, - deferred_promises, deferred_on_resolves, - deferred_on_rejects); - LeaveMicrotaskContext(); - SetCurrentContext(old_context); - Branch(IntPtrLessThan(index, num_tasks), &loop, &init_queue_loop); - } - - BIND(&if_multiple); - { - TVARIABLE(IntPtrT, inner_index, IntPtrConstant(0)); - TNode<IntPtrT> inner_length = - LoadAndUntagFixedArrayBaseLength(deferred_promises); - Label inner_loop(this, &inner_index), done(this); - - CSA_ASSERT(this, IntPtrGreaterThan(inner_length, IntPtrConstant(0))); - Goto(&inner_loop); - BIND(&inner_loop); - { - Node* const task = LoadFixedArrayElement(tasks, inner_index); - Node* const deferred_promise = - LoadFixedArrayElement(deferred_promises, inner_index); - Node* const deferred_on_resolve = - LoadFixedArrayElement(deferred_on_resolves, inner_index); - Node* const deferred_on_reject = - LoadFixedArrayElement(deferred_on_rejects, inner_index); - CallBuiltin(Builtins::kPromiseHandle, native_context, value, task, - deferred_promise, deferred_on_resolve, - deferred_on_reject); - inner_index = IntPtrAdd(inner_index, IntPtrConstant(1)); - Branch(IntPtrLessThan(inner_index, inner_length), &inner_loop, - &done); - } - BIND(&done); - - LeaveMicrotaskContext(); - SetCurrentContext(old_context); - - Branch(IntPtrLessThan(index, num_tasks), &loop, &init_queue_loop); - } + LeaveMicrotaskContext(); + SetCurrentContext(current_context); + Goto(&loop_next); } BIND(&is_unreachable); Unreachable(); - } - } -} -TF_BUILTIN(PromiseResolveThenableJob, InternalBuiltinsAssembler) { - VARIABLE(exception, MachineRepresentation::kTagged, TheHoleConstant()); - Callable call = CodeFactory::Call(isolate()); - Label reject_promise(this, Label::kDeferred); - TNode<PromiseResolveThenableJobInfo> microtask = - TNode<PromiseResolveThenableJobInfo>::UncheckedCast( - Parameter(Descriptor::kMicrotask)); - TNode<Context> context = - TNode<Context>::UncheckedCast(Parameter(Descriptor::kContext)); - - TNode<JSReceiver> thenable = TNode<JSReceiver>::UncheckedCast(LoadObjectField( - microtask, PromiseResolveThenableJobInfo::kThenableOffset)); - TNode<JSReceiver> then = TNode<JSReceiver>::UncheckedCast( - LoadObjectField(microtask, PromiseResolveThenableJobInfo::kThenOffset)); - TNode<JSFunction> resolve = TNode<JSFunction>::UncheckedCast(LoadObjectField( - microtask, PromiseResolveThenableJobInfo::kResolveOffset)); - TNode<JSFunction> reject = TNode<JSFunction>::UncheckedCast( - LoadObjectField(microtask, PromiseResolveThenableJobInfo::kRejectOffset)); - - Node* const result = CallJS(call, context, then, thenable, resolve, reject); - GotoIfException(result, &reject_promise, &exception); - Return(UndefinedConstant()); + BIND(&if_exception); + { + // Report unhandled exceptions from microtasks. + CallRuntime(Runtime::kReportMessage, current_context, + var_exception.value()); + LeaveMicrotaskContext(); + SetCurrentContext(current_context); + Goto(&loop_next); + } - BIND(&reject_promise); - CallJS(call, context, reject, UndefinedConstant(), exception.value()); - Return(UndefinedConstant()); + BIND(&loop_next); + Branch(IntPtrLessThan(index.value(), num_tasks), &loop, &init_queue_loop); + } + } } TF_BUILTIN(AbortJS, CodeStubAssembler) { |