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

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

Issue 2606093002: [promises] Refactor debug code (Closed)
Patch Set: fix stuff 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
« no previous file with comments | « src/runtime/runtime-debug.cc ('k') | test/cctest/test-code-stub-assembler.cc » ('j') | 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 // In an async function, reuse the existing stack related to the outer
65 // Promise. Otherwise, e.g. in a direct call to then, save a new stack.
66 // Promises with multiple reactions with one or more of them being async
67 // functions will not get a good stack trace, as async functions require
68 // different stacks from direct Promise use, but we save and restore a
69 // stack once for all reactions.
70 //
71 // If this isn't a case of async function, we return false, otherwise
72 // we set the correct id and return true.
73 //
74 // TODO(littledan): Improve this case.
75 bool GetDebugIdForAsyncFunction(Isolate* isolate,
76 Handle<PromiseReactionJobInfo> info,
77 int* debug_id) {
78 // deferred_promise can be Undefined, FixedArray or userland promise object.
79 if (!info->deferred_promise()->IsJSPromise()) {
80 return false;
81 }
82
83 Handle<JSPromise> deferred_promise(JSPromise::cast(info->deferred_promise()),
84 isolate);
85 Handle<Symbol> handled_by_symbol =
86 isolate->factory()->promise_handled_by_symbol();
87 Handle<Object> handled_by_promise =
88 JSObject::GetDataProperty(deferred_promise, handled_by_symbol);
89
90 if (!handled_by_promise->IsJSPromise()) {
91 return false;
92 }
93
94 Handle<JSPromise> handled_by_promise_js =
95 Handle<JSPromise>::cast(handled_by_promise);
96 Handle<Symbol> async_stack_id_symbol =
97 isolate->factory()->promise_async_stack_id_symbol();
98 Handle<Object> id =
99 JSObject::GetDataProperty(handled_by_promise_js, async_stack_id_symbol);
100
101 // id can be Undefined or Smi.
102 if (!id->IsSmi()) {
103 return false;
104 }
105
106 *debug_id = Handle<Smi>::cast(id)->value();
107 return true;
108 }
109
110 void SetDebugInfo(Isolate* isolate, Handle<PromiseReactionJobInfo> info,
111 int status) {
112 int id;
113 PromiseDebugActionName name;
114
115 if (GetDebugIdForAsyncFunction(isolate, info, &id)) {
116 name = kDebugAsyncFunction;
117 } else {
118 id = isolate->GetNextDebugMicrotaskId();
119
120 DCHECK(status != v8::Promise::kPending);
121 name = status == v8::Promise::kFulfilled ? kDebugPromiseResolve
122 : kDebugPromiseReject;
123
124 isolate->debug()->OnAsyncTaskEvent(kDebugEnqueue, id, name);
125 }
126
127 info->set_debug_id(id);
128 info->set_debug_name(name);
129 }
130
63 void EnqueuePromiseReactionJob(Isolate* isolate, 131 void EnqueuePromiseReactionJob(Isolate* isolate,
64 Handle<PromiseReactionJobInfo> info, 132 Handle<PromiseReactionJobInfo> info,
65 Handle<Object> status) { 133 int status) {
66 if (isolate->debug()->is_active()) { 134 if (isolate->debug()->is_active()) {
67 MaybeHandle<Object> maybe_result; 135 SetDebugInfo(isolate, info, status);
68 Handle<Object> deferred_obj(info->deferred_promise(), isolate); 136 }
69 137
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); 138 isolate->EnqueueMicrotask(info);
91 } 139 }
92 140
93 void PromiseSet(Isolate* isolate, Handle<JSPromise> promise, int status, 141 void PromiseSet(Isolate* isolate, Handle<JSPromise> promise, int status,
94 Handle<Object> result) { 142 Handle<Object> result) {
95 promise->set_status(status); 143 promise->set_status(status);
96 promise->set_result(*result); 144 promise->set_result(*result);
97 promise->set_deferred_promise(isolate->heap()->undefined_value()); 145 promise->set_deferred_promise(isolate->heap()->undefined_value());
98 promise->set_deferred_on_resolve(isolate->heap()->undefined_value()); 146 promise->set_deferred_on_resolve(isolate->heap()->undefined_value());
99 promise->set_deferred_on_reject(isolate->heap()->undefined_value()); 147 promise->set_deferred_on_reject(isolate->heap()->undefined_value());
100 promise->set_fulfill_reactions(isolate->heap()->undefined_value()); 148 promise->set_fulfill_reactions(isolate->heap()->undefined_value());
101 promise->set_reject_reactions(isolate->heap()->undefined_value()); 149 promise->set_reject_reactions(isolate->heap()->undefined_value());
102 } 150 }
103 151
104 void PromiseFulfill(Isolate* isolate, Handle<JSPromise> promise, 152 void PromiseFulfill(Isolate* isolate, Handle<JSPromise> promise, int status,
105 Handle<Smi> status, Handle<Object> value) { 153 Handle<Object> value) {
106 // Check if there are any callbacks. 154 // Check if there are any callbacks.
107 if (!promise->deferred_promise()->IsUndefined(isolate)) { 155 if (!promise->deferred_promise()->IsUndefined(isolate)) {
108 Handle<Object> tasks((status->value() == v8::Promise::kFulfilled) 156 Handle<Object> tasks((status == v8::Promise::kFulfilled)
109 ? promise->fulfill_reactions() 157 ? promise->fulfill_reactions()
110 : promise->reject_reactions(), 158 : promise->reject_reactions(),
111 isolate); 159 isolate);
112 Handle<PromiseReactionJobInfo> info = 160 Handle<PromiseReactionJobInfo> info =
113 isolate->factory()->NewPromiseReactionJobInfo( 161 isolate->factory()->NewPromiseReactionJobInfo(
114 promise, value, tasks, handle(promise->deferred_promise(), isolate), 162 promise, value, tasks, handle(promise->deferred_promise(), isolate),
115 handle(promise->deferred_on_resolve(), isolate), 163 handle(promise->deferred_on_resolve(), isolate),
116 handle(promise->deferred_on_reject(), isolate), 164 handle(promise->deferred_on_reject(), isolate),
117 isolate->native_context()); 165 isolate->native_context());
118 EnqueuePromiseReactionJob(isolate, info, status); 166 EnqueuePromiseReactionJob(isolate, info, status);
119 } 167 }
120 168
121 PromiseSet(isolate, promise, status->value(), value); 169 PromiseSet(isolate, promise, status, value);
122 } 170 }
123 171
124 } // namespace 172 } // namespace
125 173
126 RUNTIME_FUNCTION(Runtime_PromiseReject) { 174 RUNTIME_FUNCTION(Runtime_PromiseReject) {
127 DCHECK(args.length() == 3); 175 DCHECK(args.length() == 3);
128 HandleScope scope(isolate); 176 HandleScope scope(isolate);
129 CONVERT_ARG_HANDLE_CHECKED(JSPromise, promise, 0); 177 CONVERT_ARG_HANDLE_CHECKED(JSPromise, promise, 0);
130 CONVERT_ARG_HANDLE_CHECKED(Object, reason, 1); 178 CONVERT_ARG_HANDLE_CHECKED(Object, reason, 1);
131 CONVERT_BOOLEAN_ARG_CHECKED(debug_event, 2); 179 CONVERT_BOOLEAN_ARG_CHECKED(debug_event, 2);
132 180
133 PromiseRejectEvent(isolate, promise, promise, reason, debug_event); 181 PromiseRejectEvent(isolate, promise, promise, reason, debug_event);
182 PromiseFulfill(isolate, promise, v8::Promise::kRejected, reason);
134 183
135 Handle<Smi> status(Smi::FromInt(v8::Promise::kRejected), isolate);
136 PromiseFulfill(isolate, promise, status, reason);
137 return isolate->heap()->undefined_value(); 184 return isolate->heap()->undefined_value();
138 } 185 }
139 186
140 RUNTIME_FUNCTION(Runtime_PromiseFulfill) { 187 RUNTIME_FUNCTION(Runtime_PromiseFulfill) {
141 DCHECK(args.length() == 3); 188 DCHECK(args.length() == 3);
142 HandleScope scope(isolate); 189 HandleScope scope(isolate);
143 CONVERT_ARG_HANDLE_CHECKED(JSPromise, promise, 0); 190 CONVERT_ARG_HANDLE_CHECKED(JSPromise, promise, 0);
144 CONVERT_ARG_HANDLE_CHECKED(Smi, status, 1); 191 CONVERT_SMI_ARG_CHECKED(status, 1);
145 CONVERT_ARG_HANDLE_CHECKED(Object, value, 2); 192 CONVERT_ARG_HANDLE_CHECKED(Object, value, 2);
146 PromiseFulfill(isolate, promise, status, value); 193 PromiseFulfill(isolate, promise, status, value);
147 return isolate->heap()->undefined_value(); 194 return isolate->heap()->undefined_value();
148 } 195 }
149 196
150 RUNTIME_FUNCTION(Runtime_EnqueuePromiseReactionJob) { 197 RUNTIME_FUNCTION(Runtime_EnqueuePromiseReactionJob) {
151 HandleScope scope(isolate); 198 HandleScope scope(isolate);
152 DCHECK(args.length() == 2); 199 DCHECK(args.length() == 2);
153 CONVERT_ARG_HANDLE_CHECKED(PromiseReactionJobInfo, info, 0); 200 CONVERT_ARG_HANDLE_CHECKED(PromiseReactionJobInfo, info, 0);
154 CONVERT_ARG_HANDLE_CHECKED(Object, status, 1); 201 CONVERT_SMI_ARG_CHECKED(status, 1);
155 EnqueuePromiseReactionJob(isolate, info, status); 202 EnqueuePromiseReactionJob(isolate, info, status);
156 return isolate->heap()->undefined_value(); 203 return isolate->heap()->undefined_value();
157 } 204 }
158 205
159 RUNTIME_FUNCTION(Runtime_EnqueuePromiseResolveThenableJob) { 206 RUNTIME_FUNCTION(Runtime_EnqueuePromiseResolveThenableJob) {
160 HandleScope scope(isolate); 207 HandleScope scope(isolate);
161 DCHECK(args.length() == 3); 208 DCHECK(args.length() == 3);
162 CONVERT_ARG_HANDLE_CHECKED(JSObject, promise, 0); 209 CONVERT_ARG_HANDLE_CHECKED(JSObject, promise, 0);
163 CONVERT_ARG_HANDLE_CHECKED(JSReceiver, resolution, 1); 210 CONVERT_ARG_HANDLE_CHECKED(JSReceiver, resolution, 1);
164 CONVERT_ARG_HANDLE_CHECKED(JSReceiver, then, 2); 211 CONVERT_ARG_HANDLE_CHECKED(JSReceiver, then, 2);
165 212
166 // TODO(gsathya): Add fast path for native promises with unmodified 213 // TODO(gsathya): Add fast path for native promises with unmodified
167 // PromiseThen (which don't need these resolving functions, but 214 // PromiseThen (which don't need these resolving functions, but
168 // instead can just call resolve/reject directly). 215 // instead can just call resolve/reject directly).
169 Handle<JSFunction> resolve, reject; 216 Handle<JSFunction> resolve, reject;
170 PromiseUtils::CreateResolvingFunctions( 217 PromiseUtils::CreateResolvingFunctions(
171 isolate, promise, isolate->factory()->false_value(), &resolve, &reject); 218 isolate, promise, isolate->factory()->false_value(), &resolve, &reject);
172 219
173 Handle<Object> debug_id, debug_name; 220 int debug_id = kDebugPromiseFirstID;
221 PromiseDebugActionName debug_name = kDebugNotActive;
174 if (isolate->debug()->is_active()) { 222 if (isolate->debug()->is_active()) {
175 debug_id = 223 debug_id = isolate->GetNextDebugMicrotaskId();
176 handle(Smi::FromInt(isolate->GetNextDebugMicrotaskId()), isolate); 224 debug_name = kDebugPromiseResolveThenableJob;
177 debug_name = isolate->factory()->PromiseResolveThenableJob_string(); 225 isolate->debug()->OnAsyncTaskEvent(kDebugEnqueue, 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 } 226 }
185 227
186 Handle<PromiseResolveThenableJobInfo> info = 228 Handle<PromiseResolveThenableJobInfo> info =
187 isolate->factory()->NewPromiseResolveThenableJobInfo( 229 isolate->factory()->NewPromiseResolveThenableJobInfo(
188 resolution, then, resolve, reject, debug_id, debug_name, 230 resolution, then, resolve, reject, debug_id, debug_name,
189 isolate->native_context()); 231 isolate->native_context());
190 isolate->EnqueueMicrotask(info); 232 isolate->EnqueueMicrotask(info);
191 233
192 return isolate->heap()->undefined_value(); 234 return isolate->heap()->undefined_value();
193 } 235 }
(...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after
325 HandleScope scope(isolate); 367 HandleScope scope(isolate);
326 DCHECK_EQ(1, args.length()); 368 DCHECK_EQ(1, args.length());
327 CONVERT_ARG_HANDLE_CHECKED(JSPromise, promise, 0); 369 CONVERT_ARG_HANDLE_CHECKED(JSPromise, promise, 0);
328 isolate->RunPromiseHook(PromiseHookType::kAfter, promise, 370 isolate->RunPromiseHook(PromiseHookType::kAfter, promise,
329 isolate->factory()->undefined_value()); 371 isolate->factory()->undefined_value());
330 return isolate->heap()->undefined_value(); 372 return isolate->heap()->undefined_value();
331 } 373 }
332 374
333 } // namespace internal 375 } // namespace internal
334 } // namespace v8 376 } // namespace v8
OLDNEW
« no previous file with comments | « src/runtime/runtime-debug.cc ('k') | test/cctest/test-code-stub-assembler.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698