Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(130)

Side by Side Diff: src/runtime/runtime-promise.cc

Issue 2606093002: [promises] Refactor debug code (Closed)
Patch Set: make debug_name a smi Created 3 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« src/objects-debug.cc ('K') | « src/runtime/runtime-debug.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2016 the V8 project authors. All rights reserved. 1 // Copyright 2016 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 #include "src/runtime/runtime-utils.h" 4 #include "src/runtime/runtime-utils.h"
5 5
6 #include "src/debug/debug.h" 6 #include "src/debug/debug.h"
7 #include "src/elements.h" 7 #include "src/elements.h"
8 #include "src/promise-utils.h" 8 #include "src/promise-utils.h"
9 9
10 namespace v8 { 10 namespace v8 {
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
53 HandleScope scope(isolate); 53 HandleScope scope(isolate);
54 CONVERT_ARG_HANDLE_CHECKED(JSPromise, promise, 0); 54 CONVERT_ARG_HANDLE_CHECKED(JSPromise, promise, 0);
55 // At this point, no revocation has been issued before 55 // At this point, no revocation has been issued before
56 CHECK(!promise->has_handler()); 56 CHECK(!promise->has_handler());
57 isolate->ReportPromiseReject(promise, Handle<Object>(), 57 isolate->ReportPromiseReject(promise, Handle<Object>(),
58 v8::kPromiseHandlerAddedAfterReject); 58 v8::kPromiseHandlerAddedAfterReject);
59 return isolate->heap()->undefined_value(); 59 return isolate->heap()->undefined_value();
60 } 60 }
61 61
62 namespace { 62 namespace {
63
64 void PromiseFulfillDebugInfo(Isolate* isolate,
adamk 2016/12/30 00:10:04 This doesn't "fulfill" anything...should this be c
gsathya 2016/12/30 01:48:51 Done.
65 Handle<PromiseReactionJobInfo> info, int status) {
66 int id = isolate->GetNextDebugMicrotaskId();
67 DCHECK(status != v8::Promise::kPending);
68 PromiseDebugActionName name = status == v8::Promise::kFulfilled
69 ? DEBUG_PROMISE_RESOLVE
70 : DEBUG_PROMISE_REJECT;
71
72 isolate->debug()->OnAsyncTaskEvent(DEBUG_ENQUEUE, id, name);
73 info->set_debug_id(id);
74 info->set_debug_name(name);
75 }
76
77 // In an async function, reuse the existing stack related to the outer
78 // Promise. Otherwise, e.g. in a direct call to then, save a new stack.
79 // Promises with multiple reactions with one or more of them being async
80 // functions will not get a good stack trace, as async functions require
81 // different stacks from direct Promise use, but we save and restore a
82 // stack once for all reactions.
83 //
84 // If this isn't a case of async function, then we fall back to normal
85 // promise resolution debug events.
86 //
87 // TODO(littledan): Improve this case.
88 void AsyncFunctionDebugInfo(Isolate* isolate,
adamk 2016/12/30 00:10:04 This function name reads oddly to me, it seems to
gsathya 2016/12/30 01:48:51 Done.
89 Handle<PromiseReactionJobInfo> info, int status) {
90 // deferred_promise can be Undefined, FixedArray or userland promise object.
91 if (!info->deferred_promise()->IsJSPromise()) {
92 PromiseFulfillDebugInfo(isolate, info, status);
93 return;
adamk 2016/12/30 00:10:04 I think it would be clearer to factor these multip
gsathya 2016/12/30 01:48:51 Done.
94 }
95
96 Handle<JSPromise> deferred_promise(JSPromise::cast(info->deferred_promise()),
97 isolate);
98 Handle<Symbol> handled_by_symbol =
99 isolate->factory()->promise_handled_by_symbol();
100 Handle<Object> handled_by_promise =
101 JSObject::GetDataProperty(deferred_promise, handled_by_symbol);
102
103 if (!handled_by_promise->IsJSPromise()) {
104 PromiseFulfillDebugInfo(isolate, info, status);
105 return;
106 }
107
108 Handle<JSPromise> handled_by_promise_js =
109 Handle<JSPromise>::cast(handled_by_promise);
110 Handle<Symbol> async_stack_id_symbol =
111 isolate->factory()->promise_async_stack_id_symbol();
112 Handle<Object> id =
113 JSObject::GetDataProperty(handled_by_promise_js, async_stack_id_symbol);
114
115 // id can be Undefined or Smi.
116 if (!id->IsSmi()) {
117 PromiseFulfillDebugInfo(isolate, info, status);
118 return;
119 }
120
121 info->set_debug_id(Handle<Smi>::cast(id)->value());
122 info->set_debug_name(DEBUG_ASYNC_FUNCTION);
123 }
124
63 void EnqueuePromiseReactionJob(Isolate* isolate, 125 void EnqueuePromiseReactionJob(Isolate* isolate,
64 Handle<PromiseReactionJobInfo> info, 126 Handle<PromiseReactionJobInfo> info,
65 Handle<Object> status) { 127 int status) {
66 if (isolate->debug()->is_active()) { 128 if (isolate->debug()->is_active()) {
67 MaybeHandle<Object> maybe_result; 129 AsyncFunctionDebugInfo(isolate, info, status);
68 Handle<Object> deferred_obj(info->deferred_promise(), isolate); 130 }
69 131
70 if (info->deferred_promise()->IsFixedArray()) {
71 deferred_obj = isolate->factory()->undefined_value();
72 }
73
74 Handle<Object> argv[] = {deferred_obj, status};
75 maybe_result = Execution::TryCall(
76 isolate, isolate->promise_debug_get_info(),
77 isolate->factory()->undefined_value(), arraysize(argv), argv);
78
79 Handle<Object> result;
80 if ((maybe_result).ToHandle(&result)) {
81 CHECK(result->IsJSArray());
82 Handle<JSArray> array = Handle<JSArray>::cast(result);
83 ElementsAccessor* accessor = array->GetElementsAccessor();
84 DCHECK(accessor->HasElement(array, 0));
85 DCHECK(accessor->HasElement(array, 1));
86 info->set_debug_id(*accessor->Get(array, 0));
87 info->set_debug_name(*accessor->Get(array, 1));
88 }
89 }
90 isolate->EnqueueMicrotask(info); 132 isolate->EnqueueMicrotask(info);
91 } 133 }
92 134
93 void PromiseSet(Isolate* isolate, Handle<JSPromise> promise, int status, 135 void PromiseSet(Isolate* isolate, Handle<JSPromise> promise, int status,
94 Handle<Object> result) { 136 Handle<Object> result) {
95 promise->set_status(status); 137 promise->set_status(status);
96 promise->set_result(*result); 138 promise->set_result(*result);
97 promise->set_deferred_promise(isolate->heap()->undefined_value()); 139 promise->set_deferred_promise(isolate->heap()->undefined_value());
98 promise->set_deferred_on_resolve(isolate->heap()->undefined_value()); 140 promise->set_deferred_on_resolve(isolate->heap()->undefined_value());
99 promise->set_deferred_on_reject(isolate->heap()->undefined_value()); 141 promise->set_deferred_on_reject(isolate->heap()->undefined_value());
100 promise->set_fulfill_reactions(isolate->heap()->undefined_value()); 142 promise->set_fulfill_reactions(isolate->heap()->undefined_value());
101 promise->set_reject_reactions(isolate->heap()->undefined_value()); 143 promise->set_reject_reactions(isolate->heap()->undefined_value());
102 } 144 }
103 145
104 void PromiseFulfill(Isolate* isolate, Handle<JSPromise> promise, 146 void PromiseFulfill(Isolate* isolate, Handle<JSPromise> promise, int status,
105 Handle<Smi> status, Handle<Object> value) { 147 Handle<Object> value) {
106 // Check if there are any callbacks. 148 // Check if there are any callbacks.
107 if (!promise->deferred_promise()->IsUndefined(isolate)) { 149 if (!promise->deferred_promise()->IsUndefined(isolate)) {
108 Handle<Object> tasks((status->value() == v8::Promise::kFulfilled) 150 Handle<Object> tasks((status == v8::Promise::kFulfilled)
109 ? promise->fulfill_reactions() 151 ? promise->fulfill_reactions()
110 : promise->reject_reactions(), 152 : promise->reject_reactions(),
111 isolate); 153 isolate);
112 Handle<PromiseReactionJobInfo> info = 154 Handle<PromiseReactionJobInfo> info =
113 isolate->factory()->NewPromiseReactionJobInfo( 155 isolate->factory()->NewPromiseReactionJobInfo(
114 promise, value, tasks, handle(promise->deferred_promise(), isolate), 156 promise, value, tasks, handle(promise->deferred_promise(), isolate),
115 handle(promise->deferred_on_resolve(), isolate), 157 handle(promise->deferred_on_resolve(), isolate),
116 handle(promise->deferred_on_reject(), isolate), 158 handle(promise->deferred_on_reject(), isolate),
117 isolate->native_context()); 159 isolate->native_context());
118 EnqueuePromiseReactionJob(isolate, info, status); 160 EnqueuePromiseReactionJob(isolate, info, status);
119 } 161 }
120 162
121 PromiseSet(isolate, promise, status->value(), value); 163 PromiseSet(isolate, promise, status, value);
122 } 164 }
123 165
124 } // namespace 166 } // namespace
125 167
126 RUNTIME_FUNCTION(Runtime_PromiseReject) { 168 RUNTIME_FUNCTION(Runtime_PromiseReject) {
127 DCHECK(args.length() == 3); 169 DCHECK(args.length() == 3);
128 HandleScope scope(isolate); 170 HandleScope scope(isolate);
129 CONVERT_ARG_HANDLE_CHECKED(JSPromise, promise, 0); 171 CONVERT_ARG_HANDLE_CHECKED(JSPromise, promise, 0);
130 CONVERT_ARG_HANDLE_CHECKED(Object, reason, 1); 172 CONVERT_ARG_HANDLE_CHECKED(Object, reason, 1);
131 CONVERT_BOOLEAN_ARG_CHECKED(debug_event, 2); 173 CONVERT_BOOLEAN_ARG_CHECKED(debug_event, 2);
132 174
133 PromiseRejectEvent(isolate, promise, promise, reason, debug_event); 175 PromiseRejectEvent(isolate, promise, promise, reason, debug_event);
176 PromiseFulfill(isolate, promise, v8::Promise::kRejected, reason);
134 177
135 Handle<Smi> status(Smi::FromInt(v8::Promise::kRejected), isolate);
136 PromiseFulfill(isolate, promise, status, reason);
137 return isolate->heap()->undefined_value(); 178 return isolate->heap()->undefined_value();
138 } 179 }
139 180
140 RUNTIME_FUNCTION(Runtime_PromiseFulfill) { 181 RUNTIME_FUNCTION(Runtime_PromiseFulfill) {
141 DCHECK(args.length() == 3); 182 DCHECK(args.length() == 3);
142 HandleScope scope(isolate); 183 HandleScope scope(isolate);
143 CONVERT_ARG_HANDLE_CHECKED(JSPromise, promise, 0); 184 CONVERT_ARG_HANDLE_CHECKED(JSPromise, promise, 0);
144 CONVERT_ARG_HANDLE_CHECKED(Smi, status, 1); 185 CONVERT_SMI_ARG_CHECKED(status, 1);
145 CONVERT_ARG_HANDLE_CHECKED(Object, value, 2); 186 CONVERT_ARG_HANDLE_CHECKED(Object, value, 2);
146 PromiseFulfill(isolate, promise, status, value); 187 PromiseFulfill(isolate, promise, status, value);
147 return isolate->heap()->undefined_value(); 188 return isolate->heap()->undefined_value();
148 } 189 }
149 190
150 RUNTIME_FUNCTION(Runtime_EnqueuePromiseReactionJob) { 191 RUNTIME_FUNCTION(Runtime_EnqueuePromiseReactionJob) {
151 HandleScope scope(isolate); 192 HandleScope scope(isolate);
152 DCHECK(args.length() == 2); 193 DCHECK(args.length() == 2);
153 CONVERT_ARG_HANDLE_CHECKED(PromiseReactionJobInfo, info, 0); 194 CONVERT_ARG_HANDLE_CHECKED(PromiseReactionJobInfo, info, 0);
154 CONVERT_ARG_HANDLE_CHECKED(Object, status, 1); 195 CONVERT_SMI_ARG_CHECKED(status, 1);
155 EnqueuePromiseReactionJob(isolate, info, status); 196 EnqueuePromiseReactionJob(isolate, info, status);
156 return isolate->heap()->undefined_value(); 197 return isolate->heap()->undefined_value();
157 } 198 }
158 199
159 RUNTIME_FUNCTION(Runtime_EnqueuePromiseResolveThenableJob) { 200 RUNTIME_FUNCTION(Runtime_EnqueuePromiseResolveThenableJob) {
160 HandleScope scope(isolate); 201 HandleScope scope(isolate);
161 DCHECK(args.length() == 3); 202 DCHECK(args.length() == 3);
162 CONVERT_ARG_HANDLE_CHECKED(JSObject, promise, 0); 203 CONVERT_ARG_HANDLE_CHECKED(JSObject, promise, 0);
163 CONVERT_ARG_HANDLE_CHECKED(JSReceiver, resolution, 1); 204 CONVERT_ARG_HANDLE_CHECKED(JSReceiver, resolution, 1);
164 CONVERT_ARG_HANDLE_CHECKED(JSReceiver, then, 2); 205 CONVERT_ARG_HANDLE_CHECKED(JSReceiver, then, 2);
165 206
166 // TODO(gsathya): Add fast path for native promises with unmodified 207 // TODO(gsathya): Add fast path for native promises with unmodified
167 // PromiseThen (which don't need these resolving functions, but 208 // PromiseThen (which don't need these resolving functions, but
168 // instead can just call resolve/reject directly). 209 // instead can just call resolve/reject directly).
169 Handle<JSFunction> resolve, reject; 210 Handle<JSFunction> resolve, reject;
170 PromiseUtils::CreateResolvingFunctions( 211 PromiseUtils::CreateResolvingFunctions(
171 isolate, promise, isolate->factory()->false_value(), &resolve, &reject); 212 isolate, promise, isolate->factory()->false_value(), &resolve, &reject);
172 213
173 Handle<Object> debug_id, debug_name; 214 int debug_id = 0;
adamk 2016/12/30 00:10:04 Please define a constant somewhere for this 0, som
gsathya 2016/12/30 01:48:51 Done.
215 PromiseDebugActionName debug_name = DEBUG_NOT_ACTIVE;
174 if (isolate->debug()->is_active()) { 216 if (isolate->debug()->is_active()) {
175 debug_id = 217 debug_id = isolate->GetNextDebugMicrotaskId();
176 handle(Smi::FromInt(isolate->GetNextDebugMicrotaskId()), isolate); 218 debug_name = DEBUG_PROMISE_RESOLVE_THENABLE_JOB;
177 debug_name = isolate->factory()->PromiseResolveThenableJob_string(); 219 isolate->debug()->OnAsyncTaskEvent(DEBUG_ENQUEUE, debug_id, debug_name);
178 isolate->debug()->OnAsyncTaskEvent(isolate->factory()->enqueue_string(),
179 debug_id,
180 Handle<String>::cast(debug_name));
181 } else {
182 debug_id = isolate->factory()->undefined_value();
183 debug_name = isolate->factory()->undefined_value();
184 } 220 }
185 221
186 Handle<PromiseResolveThenableJobInfo> info = 222 Handle<PromiseResolveThenableJobInfo> info =
187 isolate->factory()->NewPromiseResolveThenableJobInfo( 223 isolate->factory()->NewPromiseResolveThenableJobInfo(
188 resolution, then, resolve, reject, debug_id, debug_name, 224 resolution, then, resolve, reject, debug_id, debug_name,
189 isolate->native_context()); 225 isolate->native_context());
190 isolate->EnqueueMicrotask(info); 226 isolate->EnqueueMicrotask(info);
191 227
192 return isolate->heap()->undefined_value(); 228 return isolate->heap()->undefined_value();
193 } 229 }
(...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after
325 HandleScope scope(isolate); 361 HandleScope scope(isolate);
326 DCHECK_EQ(1, args.length()); 362 DCHECK_EQ(1, args.length());
327 CONVERT_ARG_HANDLE_CHECKED(JSPromise, promise, 0); 363 CONVERT_ARG_HANDLE_CHECKED(JSPromise, promise, 0);
328 isolate->RunPromiseHook(PromiseHookType::kAfter, promise, 364 isolate->RunPromiseHook(PromiseHookType::kAfter, promise,
329 isolate->factory()->undefined_value()); 365 isolate->factory()->undefined_value());
330 return isolate->heap()->undefined_value(); 366 return isolate->heap()->undefined_value();
331 } 367 }
332 368
333 } // namespace internal 369 } // namespace internal
334 } // namespace v8 370 } // namespace v8
OLDNEW
« src/objects-debug.cc ('K') | « src/runtime/runtime-debug.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698