summaryrefslogtreecommitdiff
path: root/deps/v8/src/builtins/builtins-internal-gen.cc
diff options
context:
space:
mode:
authorMyles Borins <mylesborins@google.com>2018-04-10 21:39:51 -0400
committerMyles Borins <mylesborins@google.com>2018-04-11 13:22:42 -0400
commit12a1b9b8049462e47181a298120243dc83e81c55 (patch)
tree8605276308c8b4e3597516961266bae1af57557a /deps/v8/src/builtins/builtins-internal-gen.cc
parent78cd8263354705b767ef8c6a651740efe4931ba0 (diff)
downloadnode-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.cc359
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) {