| OLD | NEW |
| 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 | 4 |
| 5 #include "src/builtins/builtins-promise.h" | 5 #include "src/builtins/builtins-promise.h" |
| 6 #include "src/builtins/builtins-utils.h" | 6 #include "src/builtins/builtins-utils.h" |
| 7 #include "src/builtins/builtins.h" | 7 #include "src/builtins/builtins.h" |
| 8 #include "src/code-factory.h" | 8 #include "src/code-factory.h" |
| 9 #include "src/code-stub-assembler.h" | 9 #include "src/code-stub-assembler.h" |
| 10 #include "src/promise-utils.h" | 10 #include "src/promise-utils.h" |
| 11 | 11 |
| 12 namespace v8 { | 12 namespace v8 { |
| 13 namespace internal { | 13 namespace internal { |
| 14 | 14 |
| 15 typedef compiler::Node Node; | 15 typedef compiler::Node Node; |
| 16 typedef CodeStubAssembler::ParameterMode ParameterMode; | 16 typedef CodeStubAssembler::ParameterMode ParameterMode; |
| 17 typedef compiler::CodeAssemblerState CodeAssemblerState; | 17 typedef compiler::CodeAssemblerState CodeAssemblerState; |
| 18 | 18 |
| 19 Node* PromiseBuiltinsAssembler::AllocateAndInitPromise(Node* context, |
| 20 Node* parent) { |
| 21 Node* const instance = AllocateJSPromise(context); |
| 22 PromiseInit(instance); |
| 23 |
| 24 Label out(this); |
| 25 GotoUnless(IsPromiseHookEnabled(), &out); |
| 26 CallRuntime(Runtime::kPromiseHookInit, context, instance, parent); |
| 27 Goto(&out); |
| 28 |
| 29 Bind(&out); |
| 30 return instance; |
| 31 } |
| 32 |
| 19 Node* PromiseBuiltinsAssembler::CreatePromiseResolvingFunctionsContext( | 33 Node* PromiseBuiltinsAssembler::CreatePromiseResolvingFunctionsContext( |
| 20 Node* promise, Node* debug_event, Node* native_context) { | 34 Node* promise, Node* debug_event, Node* native_context) { |
| 21 Node* const context = | 35 Node* const context = |
| 22 Allocate(FixedArray::SizeFor(PromiseUtils::kPromiseContextLength)); | 36 Allocate(FixedArray::SizeFor(PromiseUtils::kPromiseContextLength)); |
| 23 StoreMapNoWriteBarrier(context, Heap::kFunctionContextMapRootIndex); | 37 StoreMapNoWriteBarrier(context, Heap::kFunctionContextMapRootIndex); |
| 24 StoreObjectFieldNoWriteBarrier( | 38 StoreObjectFieldNoWriteBarrier( |
| 25 context, FixedArray::kLengthOffset, | 39 context, FixedArray::kLengthOffset, |
| 26 SmiConstant(PromiseUtils::kPromiseContextLength)); | 40 SmiConstant(PromiseUtils::kPromiseContextLength)); |
| 27 | 41 |
| 28 Node* const empty_fn = | 42 Node* const empty_fn = |
| (...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 194 Node* const promise_fun = | 208 Node* const promise_fun = |
| 195 LoadContextElement(native_context, Context::PROMISE_FUNCTION_INDEX); | 209 LoadContextElement(native_context, Context::PROMISE_FUNCTION_INDEX); |
| 196 | 210 |
| 197 // 3. Let C be ? SpeciesConstructor(promise, %Promise%). | 211 // 3. Let C be ? SpeciesConstructor(promise, %Promise%). |
| 198 Node* constructor = SpeciesConstructor(context, promise, promise_fun); | 212 Node* constructor = SpeciesConstructor(context, promise, promise_fun); |
| 199 | 213 |
| 200 // 4. Let resultCapability be ? NewPromiseCapability(C). | 214 // 4. Let resultCapability be ? NewPromiseCapability(C). |
| 201 Callable call_callable = CodeFactory::Call(isolate); | 215 Callable call_callable = CodeFactory::Call(isolate); |
| 202 Label fast_promise_capability(this), promise_capability(this), | 216 Label fast_promise_capability(this), promise_capability(this), |
| 203 perform_promise_then(this); | 217 perform_promise_then(this); |
| 204 Variable var_deferred(this, MachineRepresentation::kTagged); | 218 Variable var_deferred_promise(this, MachineRepresentation::kTagged), |
| 219 var_deferred_on_resolve(this, MachineRepresentation::kTagged), |
| 220 var_deferred_on_reject(this, MachineRepresentation::kTagged); |
| 205 | 221 |
| 206 Branch(WordEqual(promise_fun, constructor), &fast_promise_capability, | 222 Branch(WordEqual(promise_fun, constructor), &fast_promise_capability, |
| 207 &promise_capability); | 223 &promise_capability); |
| 208 | 224 |
| 209 // TODO(gsathya): Remove deferred object and move | |
| 210 // NewPromiseCapabability functions to TF. | |
| 211 Bind(&fast_promise_capability); | 225 Bind(&fast_promise_capability); |
| 212 { | 226 { |
| 213 // TODO(gsathya): Move this to TF. | 227 Node* const deferred_promise = AllocateAndInitPromise(context, promise); |
| 214 Node* const promise_internal_capability = LoadContextElement( | 228 PromiseInit(deferred_promise); |
| 215 native_context, Context::INTERNAL_PROMISE_CAPABILITY_INDEX); | 229 var_deferred_promise.Bind(deferred_promise); |
| 216 Node* const capability = | 230 var_deferred_on_resolve.Bind(UndefinedConstant()); |
| 217 CallJS(call_callable, context, promise_internal_capability, | 231 var_deferred_on_reject.Bind(UndefinedConstant()); |
| 218 UndefinedConstant(), promise); | |
| 219 var_deferred.Bind(capability); | |
| 220 Goto(&perform_promise_then); | 232 Goto(&perform_promise_then); |
| 221 } | 233 } |
| 222 | 234 |
| 223 Bind(&promise_capability); | 235 Bind(&promise_capability); |
| 224 { | 236 { |
| 225 // TODO(gsathya): Move this to TF. | 237 // TODO(gsathya): Move this to TF. |
| 226 Node* const new_promise_capability = LoadContextElement( | 238 Node* const new_promise_capability = LoadContextElement( |
| 227 native_context, Context::NEW_PROMISE_CAPABILITY_INDEX); | 239 native_context, Context::NEW_PROMISE_CAPABILITY_INDEX); |
| 228 Node* const capability = | 240 Node* const deferred = |
| 229 CallJS(call_callable, context, new_promise_capability, | 241 CallJS(call_callable, context, new_promise_capability, |
| 230 UndefinedConstant(), constructor); | 242 UndefinedConstant(), constructor); |
| 231 var_deferred.Bind(capability); | 243 Callable getproperty_callable = CodeFactory::GetProperty(isolate); |
| 244 Node* key = HeapConstant(isolate->factory()->promise_string()); |
| 245 Node* const deferred_promise = |
| 246 CallStub(getproperty_callable, context, deferred, key); |
| 247 var_deferred_promise.Bind(deferred_promise); |
| 248 |
| 249 key = HeapConstant(isolate->factory()->resolve_string()); |
| 250 Node* const deferred_on_resolve = |
| 251 CallStub(getproperty_callable, context, deferred, key); |
| 252 var_deferred_on_resolve.Bind(deferred_on_resolve); |
| 253 |
| 254 key = HeapConstant(isolate->factory()->reject_string()); |
| 255 Node* const deferred_on_reject = |
| 256 CallStub(getproperty_callable, context, deferred, key); |
| 257 var_deferred_on_reject.Bind(deferred_on_reject); |
| 258 |
| 232 Goto(&perform_promise_then); | 259 Goto(&perform_promise_then); |
| 233 } | 260 } |
| 234 | 261 |
| 235 // 5. Return PerformPromiseThen(promise, onFulfilled, onRejected, | 262 // 5. Return PerformPromiseThen(promise, onFulfilled, onRejected, |
| 236 // resultCapability). | 263 // resultCapability). |
| 237 Bind(&perform_promise_then); | 264 Bind(&perform_promise_then); |
| 238 Node* const result = InternalPerformPromiseThen( | 265 Node* const result = InternalPerformPromiseThen( |
| 239 context, promise, on_resolve, on_reject, var_deferred.value()); | 266 context, promise, on_resolve, on_reject, var_deferred_promise.value(), |
| 267 var_deferred_on_resolve.value(), var_deferred_on_reject.value()); |
| 240 return result; | 268 return result; |
| 241 } | 269 } |
| 242 | 270 |
| 243 Node* PromiseBuiltinsAssembler::InternalPerformPromiseThen(Node* context, | 271 Node* PromiseBuiltinsAssembler::InternalPerformPromiseThen( |
| 244 Node* promise, | 272 Node* context, Node* promise, Node* on_resolve, Node* on_reject, |
| 245 Node* on_resolve, | 273 Node* deferred_promise, Node* deferred_on_resolve, |
| 246 Node* on_reject, | 274 Node* deferred_on_reject) { |
| 247 Node* deferred) { | |
| 248 Node* const native_context = LoadNativeContext(context); | 275 Node* const native_context = LoadNativeContext(context); |
| 249 | 276 |
| 250 Variable var_on_resolve(this, MachineRepresentation::kTagged), | 277 Variable var_on_resolve(this, MachineRepresentation::kTagged), |
| 251 var_on_reject(this, MachineRepresentation::kTagged); | 278 var_on_reject(this, MachineRepresentation::kTagged); |
| 252 | 279 |
| 253 var_on_resolve.Bind(on_resolve); | 280 var_on_resolve.Bind(on_resolve); |
| 254 var_on_reject.Bind(on_reject); | 281 var_on_reject.Bind(on_reject); |
| 255 | 282 |
| 256 Label out(this), if_onresolvenotcallable(this), onrejectcheck(this), | 283 Label out(this), if_onresolvenotcallable(this), onrejectcheck(this), |
| 257 append_callbacks(this); | 284 append_callbacks(this); |
| (...skipping 27 matching lines...) Expand all Loading... |
| 285 } | 312 } |
| 286 } | 313 } |
| 287 | 314 |
| 288 Bind(&append_callbacks); | 315 Bind(&append_callbacks); |
| 289 { | 316 { |
| 290 Label fulfilled_check(this); | 317 Label fulfilled_check(this); |
| 291 Node* const status = LoadObjectField(promise, JSPromise::kStatusOffset); | 318 Node* const status = LoadObjectField(promise, JSPromise::kStatusOffset); |
| 292 GotoUnless(SmiEqual(status, SmiConstant(v8::Promise::kPending)), | 319 GotoUnless(SmiEqual(status, SmiConstant(v8::Promise::kPending)), |
| 293 &fulfilled_check); | 320 &fulfilled_check); |
| 294 | 321 |
| 295 Node* const existing_deferred = | 322 Node* const existing_deferred_promise = |
| 296 LoadObjectField(promise, JSPromise::kDeferredOffset); | 323 LoadObjectField(promise, JSPromise::kDeferredPromiseOffset); |
| 297 | 324 |
| 298 Label if_noexistingcallbacks(this), if_existingcallbacks(this); | 325 Label if_noexistingcallbacks(this), if_existingcallbacks(this); |
| 299 Branch(IsUndefined(existing_deferred), &if_noexistingcallbacks, | 326 Branch(IsUndefined(existing_deferred_promise), &if_noexistingcallbacks, |
| 300 &if_existingcallbacks); | 327 &if_existingcallbacks); |
| 301 | 328 |
| 302 Bind(&if_noexistingcallbacks); | 329 Bind(&if_noexistingcallbacks); |
| 303 { | 330 { |
| 304 // Store callbacks directly in the slots. | 331 // Store callbacks directly in the slots. |
| 305 StoreObjectField(promise, JSPromise::kDeferredOffset, deferred); | 332 StoreObjectField(promise, JSPromise::kDeferredPromiseOffset, |
| 333 deferred_promise); |
| 334 StoreObjectField(promise, JSPromise::kDeferredOnResolveOffset, |
| 335 deferred_on_resolve); |
| 336 StoreObjectField(promise, JSPromise::kDeferredOnRejectOffset, |
| 337 deferred_on_reject); |
| 306 StoreObjectField(promise, JSPromise::kFulfillReactionsOffset, | 338 StoreObjectField(promise, JSPromise::kFulfillReactionsOffset, |
| 307 var_on_resolve.value()); | 339 var_on_resolve.value()); |
| 308 StoreObjectField(promise, JSPromise::kRejectReactionsOffset, | 340 StoreObjectField(promise, JSPromise::kRejectReactionsOffset, |
| 309 var_on_reject.value()); | 341 var_on_reject.value()); |
| 310 Goto(&out); | 342 Goto(&out); |
| 311 } | 343 } |
| 312 | 344 |
| 313 Bind(&if_existingcallbacks); | 345 Bind(&if_existingcallbacks); |
| 314 { | 346 { |
| 315 Label if_singlecallback(this), if_multiplecallbacks(this); | 347 Label if_singlecallback(this), if_multiplecallbacks(this); |
| 316 BranchIfJSObject(existing_deferred, &if_singlecallback, | 348 BranchIfJSObject(existing_deferred_promise, &if_singlecallback, |
| 317 &if_multiplecallbacks); | 349 &if_multiplecallbacks); |
| 318 | 350 |
| 319 Bind(&if_singlecallback); | 351 Bind(&if_singlecallback); |
| 320 { | 352 { |
| 321 // Create new FixedArrays to store callbacks, and migrate | 353 // Create new FixedArrays to store callbacks, and migrate |
| 322 // existing callbacks. | 354 // existing callbacks. |
| 323 Node* const deferreds = | 355 Node* const deferred_promise_arr = |
| 324 AllocateFixedArray(FAST_ELEMENTS, IntPtrConstant(2)); | 356 AllocateFixedArray(FAST_ELEMENTS, IntPtrConstant(2)); |
| 325 StoreFixedArrayElement(deferreds, 0, existing_deferred); | 357 StoreFixedArrayElement(deferred_promise_arr, 0, |
| 326 StoreFixedArrayElement(deferreds, 1, deferred); | 358 existing_deferred_promise); |
| 359 StoreFixedArrayElement(deferred_promise_arr, 1, deferred_promise); |
| 360 |
| 361 Node* const deferred_on_resolve_arr = |
| 362 AllocateFixedArray(FAST_ELEMENTS, IntPtrConstant(2)); |
| 363 StoreFixedArrayElement( |
| 364 deferred_on_resolve_arr, 0, |
| 365 LoadObjectField(promise, JSPromise::kDeferredOnResolveOffset)); |
| 366 StoreFixedArrayElement(deferred_on_resolve_arr, 1, deferred_on_resolve); |
| 367 |
| 368 Node* const deferred_on_reject_arr = |
| 369 AllocateFixedArray(FAST_ELEMENTS, IntPtrConstant(2)); |
| 370 StoreFixedArrayElement( |
| 371 deferred_on_reject_arr, 0, |
| 372 LoadObjectField(promise, JSPromise::kDeferredOnRejectOffset)); |
| 373 StoreFixedArrayElement(deferred_on_reject_arr, 1, deferred_on_reject); |
| 327 | 374 |
| 328 Node* const fulfill_reactions = | 375 Node* const fulfill_reactions = |
| 329 AllocateFixedArray(FAST_ELEMENTS, IntPtrConstant(2)); | 376 AllocateFixedArray(FAST_ELEMENTS, IntPtrConstant(2)); |
| 330 StoreFixedArrayElement( | 377 StoreFixedArrayElement( |
| 331 fulfill_reactions, 0, | 378 fulfill_reactions, 0, |
| 332 LoadObjectField(promise, JSPromise::kFulfillReactionsOffset)); | 379 LoadObjectField(promise, JSPromise::kFulfillReactionsOffset)); |
| 333 StoreFixedArrayElement(fulfill_reactions, 1, var_on_resolve.value()); | 380 StoreFixedArrayElement(fulfill_reactions, 1, var_on_resolve.value()); |
| 334 | 381 |
| 335 Node* const reject_reactions = | 382 Node* const reject_reactions = |
| 336 AllocateFixedArray(FAST_ELEMENTS, IntPtrConstant(2)); | 383 AllocateFixedArray(FAST_ELEMENTS, IntPtrConstant(2)); |
| 337 StoreFixedArrayElement( | 384 StoreFixedArrayElement( |
| 338 reject_reactions, 0, | 385 reject_reactions, 0, |
| 339 LoadObjectField(promise, JSPromise::kRejectReactionsOffset)); | 386 LoadObjectField(promise, JSPromise::kRejectReactionsOffset)); |
| 340 StoreFixedArrayElement(reject_reactions, 1, var_on_reject.value()); | 387 StoreFixedArrayElement(reject_reactions, 1, var_on_reject.value()); |
| 341 | 388 |
| 342 // Store new FixedArrays in promise. | 389 // Store new FixedArrays in promise. |
| 343 StoreObjectField(promise, JSPromise::kDeferredOffset, deferreds); | 390 StoreObjectField(promise, JSPromise::kDeferredPromiseOffset, |
| 391 deferred_promise_arr); |
| 392 StoreObjectField(promise, JSPromise::kDeferredOnResolveOffset, |
| 393 deferred_on_resolve_arr); |
| 394 StoreObjectField(promise, JSPromise::kDeferredOnRejectOffset, |
| 395 deferred_on_reject_arr); |
| 344 StoreObjectField(promise, JSPromise::kFulfillReactionsOffset, | 396 StoreObjectField(promise, JSPromise::kFulfillReactionsOffset, |
| 345 fulfill_reactions); | 397 fulfill_reactions); |
| 346 StoreObjectField(promise, JSPromise::kRejectReactionsOffset, | 398 StoreObjectField(promise, JSPromise::kRejectReactionsOffset, |
| 347 reject_reactions); | 399 reject_reactions); |
| 348 Goto(&out); | 400 Goto(&out); |
| 349 } | 401 } |
| 350 | 402 |
| 351 Bind(&if_multiplecallbacks); | 403 Bind(&if_multiplecallbacks); |
| 352 { | 404 { |
| 353 AppendPromiseCallback(JSPromise::kDeferredOffset, promise, deferred); | 405 AppendPromiseCallback(JSPromise::kDeferredPromiseOffset, promise, |
| 406 deferred_promise); |
| 407 AppendPromiseCallback(JSPromise::kDeferredOnResolveOffset, promise, |
| 408 deferred_on_resolve); |
| 409 AppendPromiseCallback(JSPromise::kDeferredOnRejectOffset, promise, |
| 410 deferred_on_reject); |
| 354 AppendPromiseCallback(JSPromise::kFulfillReactionsOffset, promise, | 411 AppendPromiseCallback(JSPromise::kFulfillReactionsOffset, promise, |
| 355 var_on_resolve.value()); | 412 var_on_resolve.value()); |
| 356 AppendPromiseCallback(JSPromise::kRejectReactionsOffset, promise, | 413 AppendPromiseCallback(JSPromise::kRejectReactionsOffset, promise, |
| 357 var_on_reject.value()); | 414 var_on_reject.value()); |
| 358 Goto(&out); | 415 Goto(&out); |
| 359 } | 416 } |
| 360 } | 417 } |
| 361 | 418 |
| 362 Bind(&fulfilled_check); | 419 Bind(&fulfilled_check); |
| 363 { | 420 { |
| 364 Label reject(this); | 421 Label reject(this); |
| 365 Node* const result = LoadObjectField(promise, JSPromise::kResultOffset); | 422 Node* const result = LoadObjectField(promise, JSPromise::kResultOffset); |
| 366 GotoUnless(WordEqual(status, SmiConstant(v8::Promise::kFulfilled)), | 423 GotoUnless(WordEqual(status, SmiConstant(v8::Promise::kFulfilled)), |
| 367 &reject); | 424 &reject); |
| 368 | 425 |
| 369 // TODO(gsathya): Move this to TF. | 426 Node* info = AllocatePromiseReactionJobInfo( |
| 370 CallRuntime(Runtime::kEnqueuePromiseReactionJob, context, promise, result, | 427 promise, result, var_on_resolve.value(), deferred_promise, |
| 371 var_on_resolve.value(), deferred, | 428 deferred_on_resolve, deferred_on_reject, context); |
| 429 // TODO(gsathya): Move this to TF |
| 430 CallRuntime(Runtime::kEnqueuePromiseReactionJob, context, info, |
| 372 SmiConstant(v8::Promise::kFulfilled)); | 431 SmiConstant(v8::Promise::kFulfilled)); |
| 373 Goto(&out); | 432 Goto(&out); |
| 374 | 433 |
| 375 Bind(&reject); | 434 Bind(&reject); |
| 376 { | 435 { |
| 377 Node* const has_handler = PromiseHasHandler(promise); | 436 Node* const has_handler = PromiseHasHandler(promise); |
| 378 Label enqueue(this); | 437 Label enqueue(this); |
| 379 | 438 |
| 380 // TODO(gsathya): Fold these runtime calls and move to TF. | 439 // TODO(gsathya): Fold these runtime calls and move to TF. |
| 381 GotoIf(has_handler, &enqueue); | 440 GotoIf(has_handler, &enqueue); |
| 382 CallRuntime(Runtime::kPromiseRevokeReject, context, promise); | 441 CallRuntime(Runtime::kPromiseRevokeReject, context, promise); |
| 383 Goto(&enqueue); | 442 Goto(&enqueue); |
| 384 | 443 |
| 385 Bind(&enqueue); | 444 Bind(&enqueue); |
| 386 { | 445 { |
| 387 CallRuntime(Runtime::kEnqueuePromiseReactionJob, context, promise, | 446 Node* info = AllocatePromiseReactionJobInfo( |
| 388 result, var_on_reject.value(), deferred, | 447 promise, result, var_on_reject.value(), deferred_promise, |
| 448 deferred_on_resolve, deferred_on_reject, context); |
| 449 // TODO(gsathya): Move this to TF |
| 450 CallRuntime(Runtime::kEnqueuePromiseReactionJob, context, info, |
| 389 SmiConstant(v8::Promise::kRejected)); | 451 SmiConstant(v8::Promise::kRejected)); |
| 390 | |
| 391 Goto(&out); | 452 Goto(&out); |
| 392 } | 453 } |
| 393 } | 454 } |
| 394 } | 455 } |
| 395 } | 456 } |
| 396 | 457 |
| 397 Bind(&out); | 458 Bind(&out); |
| 398 PromiseSetHasHandler(promise); | 459 PromiseSetHasHandler(promise); |
| 399 | 460 return deferred_promise; |
| 400 // TODO(gsathya): This call will be removed once we don't have to | |
| 401 // deal with deferred objects. | |
| 402 Isolate* isolate = this->isolate(); | |
| 403 Callable getproperty_callable = CodeFactory::GetProperty(isolate); | |
| 404 Node* const key = | |
| 405 HeapConstant(isolate->factory()->NewStringFromAsciiChecked("promise")); | |
| 406 Node* const result = CallStub(getproperty_callable, context, deferred, key); | |
| 407 | |
| 408 return result; | |
| 409 } | 461 } |
| 410 | 462 |
| 411 // Promise fast path implementations rely on unmodified JSPromise instances. | 463 // Promise fast path implementations rely on unmodified JSPromise instances. |
| 412 // We use a fairly coarse granularity for this and simply check whether both | 464 // We use a fairly coarse granularity for this and simply check whether both |
| 413 // the promise itself is unmodified (i.e. its map has not changed) and its | 465 // the promise itself is unmodified (i.e. its map has not changed) and its |
| 414 // prototype is unmodified. | 466 // prototype is unmodified. |
| 415 // TODO(gsathya): Refactor this out to prevent code dupe with builtins-regexp | 467 // TODO(gsathya): Refactor this out to prevent code dupe with builtins-regexp |
| 416 void PromiseBuiltinsAssembler::BranchIfFastPath(Node* context, Node* promise, | 468 void PromiseBuiltinsAssembler::BranchIfFastPath(Node* context, Node* promise, |
| 417 Label* if_isunmodified, | 469 Label* if_isunmodified, |
| 418 Label* if_ismodified) { | 470 Label* if_ismodified) { |
| (...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 550 Node* const key = | 602 Node* const key = |
| 551 HeapConstant(isolate->factory()->promise_handled_by_symbol()); | 603 HeapConstant(isolate->factory()->promise_handled_by_symbol()); |
| 552 CallRuntime(Runtime::kSetProperty, context, result, key, promise, | 604 CallRuntime(Runtime::kSetProperty, context, result, key, promise, |
| 553 SmiConstant(STRICT)); | 605 SmiConstant(STRICT)); |
| 554 Goto(&enqueue); | 606 Goto(&enqueue); |
| 555 | 607 |
| 556 // 12. Perform EnqueueJob("PromiseJobs", | 608 // 12. Perform EnqueueJob("PromiseJobs", |
| 557 // PromiseResolveThenableJob, « promise, resolution, thenAction | 609 // PromiseResolveThenableJob, « promise, resolution, thenAction |
| 558 // »). | 610 // »). |
| 559 Bind(&enqueue); | 611 Bind(&enqueue); |
| 612 // TODO(gsathya): Move this to TF |
| 560 CallRuntime(Runtime::kEnqueuePromiseResolveThenableJob, context, promise, | 613 CallRuntime(Runtime::kEnqueuePromiseResolveThenableJob, context, promise, |
| 561 result, var_then.value()); | 614 result, var_then.value()); |
| 562 Goto(&out); | 615 Goto(&out); |
| 563 } | 616 } |
| 564 | 617 |
| 565 // 7.b Return FulfillPromise(promise, resolution). | 618 // 7.b Return FulfillPromise(promise, resolution). |
| 566 Bind(&fulfill); | 619 Bind(&fulfill); |
| 567 { | 620 { |
| 568 CallRuntime(Runtime::kPromiseFulfill, context, promise, | 621 CallRuntime(Runtime::kPromiseFulfill, context, promise, |
| 569 SmiConstant(v8::Promise::kFulfilled), result); | 622 SmiConstant(v8::Promise::kFulfilled), result); |
| (...skipping 190 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 760 Node* const message_id = | 813 Node* const message_id = |
| 761 SmiConstant(MessageTemplate::kResolverNotAFunction); | 814 SmiConstant(MessageTemplate::kResolverNotAFunction); |
| 762 CallRuntime(Runtime::kThrowTypeError, context, message_id, executor); | 815 CallRuntime(Runtime::kThrowTypeError, context, message_id, executor); |
| 763 Return(UndefinedConstant()); // Never reached. | 816 Return(UndefinedConstant()); // Never reached. |
| 764 } | 817 } |
| 765 } | 818 } |
| 766 | 819 |
| 767 TF_BUILTIN(PromiseInternalConstructor, PromiseBuiltinsAssembler) { | 820 TF_BUILTIN(PromiseInternalConstructor, PromiseBuiltinsAssembler) { |
| 768 Node* const parent = Parameter(1); | 821 Node* const parent = Parameter(1); |
| 769 Node* const context = Parameter(4); | 822 Node* const context = Parameter(4); |
| 770 Node* const instance = AllocateJSPromise(context); | 823 Return(AllocateAndInitPromise(context, parent)); |
| 771 PromiseInit(instance); | |
| 772 | |
| 773 Label out(this); | |
| 774 GotoUnless(IsPromiseHookEnabled(), &out); | |
| 775 CallRuntime(Runtime::kPromiseHookInit, context, instance, parent); | |
| 776 Goto(&out); | |
| 777 Bind(&out); | |
| 778 | |
| 779 Return(instance); | |
| 780 } | 824 } |
| 781 | 825 |
| 782 TF_BUILTIN(PromiseCreateAndSet, PromiseBuiltinsAssembler) { | 826 TF_BUILTIN(PromiseCreateAndSet, PromiseBuiltinsAssembler) { |
| 783 Node* const status = Parameter(1); | 827 Node* const status = Parameter(1); |
| 784 Node* const result = Parameter(2); | 828 Node* const result = Parameter(2); |
| 785 Node* const context = Parameter(5); | 829 Node* const context = Parameter(5); |
| 786 | 830 |
| 787 Node* const instance = AllocateJSPromise(context); | 831 Node* const instance = AllocateJSPromise(context); |
| 788 PromiseSet(instance, status, result); | 832 PromiseSet(instance, status, result); |
| 789 | 833 |
| (...skipping 17 matching lines...) Expand all Loading... |
| 807 Return(result); | 851 Return(result); |
| 808 | 852 |
| 809 Bind(&if_notpromise); | 853 Bind(&if_notpromise); |
| 810 Return(FalseConstant()); | 854 Return(FalseConstant()); |
| 811 } | 855 } |
| 812 | 856 |
| 813 TF_BUILTIN(PerformPromiseThen, PromiseBuiltinsAssembler) { | 857 TF_BUILTIN(PerformPromiseThen, PromiseBuiltinsAssembler) { |
| 814 Node* const promise = Parameter(1); | 858 Node* const promise = Parameter(1); |
| 815 Node* const on_resolve = Parameter(2); | 859 Node* const on_resolve = Parameter(2); |
| 816 Node* const on_reject = Parameter(3); | 860 Node* const on_reject = Parameter(3); |
| 817 Node* const deferred = Parameter(4); | 861 Node* const deferred_promise = Parameter(4); |
| 818 Node* const context = Parameter(7); | 862 Node* const context = Parameter(7); |
| 819 | 863 |
| 820 Node* const result = InternalPerformPromiseThen(context, promise, on_resolve, | 864 // No deferred_on_resolve/deferred_on_reject because this is just an |
| 821 on_reject, deferred); | 865 // internal promise created by async-await. |
| 866 Node* const result = InternalPerformPromiseThen( |
| 867 context, promise, on_resolve, on_reject, deferred_promise, |
| 868 UndefinedConstant(), UndefinedConstant()); |
| 822 | 869 |
| 823 // TODO(gsathya): This is unused, but value is returned according to spec. | 870 // TODO(gsathya): This is unused, but value is returned according to spec. |
| 824 Return(result); | 871 Return(result); |
| 825 } | 872 } |
| 826 | 873 |
| 827 // ES#sec-promise.prototype.then | 874 // ES#sec-promise.prototype.then |
| 828 // Promise.prototype.catch ( onFulfilled, onRejected ) | 875 // Promise.prototype.catch ( onFulfilled, onRejected ) |
| 829 TF_BUILTIN(PromiseThen, PromiseBuiltinsAssembler) { | 876 TF_BUILTIN(PromiseThen, PromiseBuiltinsAssembler) { |
| 830 // 1. Let promise be the this value. | 877 // 1. Let promise be the this value. |
| 831 Node* const promise = Parameter(0); | 878 Node* const promise = Parameter(0); |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 904 { | 951 { |
| 905 CallJS(call_callable, context, on_reject, UndefinedConstant(), exception); | 952 CallJS(call_callable, context, on_reject, UndefinedConstant(), exception); |
| 906 Return(UndefinedConstant()); | 953 Return(UndefinedConstant()); |
| 907 } | 954 } |
| 908 } | 955 } |
| 909 | 956 |
| 910 TF_BUILTIN(PromiseHandle, PromiseBuiltinsAssembler) { | 957 TF_BUILTIN(PromiseHandle, PromiseBuiltinsAssembler) { |
| 911 Node* const promise = Parameter(1); | 958 Node* const promise = Parameter(1); |
| 912 Node* const value = Parameter(2); | 959 Node* const value = Parameter(2); |
| 913 Node* const handler = Parameter(3); | 960 Node* const handler = Parameter(3); |
| 914 Node* const deferred = Parameter(4); | 961 Node* const deferred_promise = Parameter(4); |
| 915 Node* const context = Parameter(7); | 962 Node* const deferred_on_resolve = Parameter(5); |
| 963 Node* const deferred_on_reject = Parameter(6); |
| 964 Node* const context = Parameter(9); |
| 916 Isolate* isolate = this->isolate(); | 965 Isolate* isolate = this->isolate(); |
| 917 | 966 |
| 918 // Get promise from deferred | |
| 919 // TODO(gsathya): Remove this lookup by getting rid of the deferred object. | |
| 920 Callable getproperty_callable = CodeFactory::GetProperty(isolate); | |
| 921 Node* const key = HeapConstant(isolate->factory()->promise_string()); | |
| 922 Node* const deferred_promise = | |
| 923 CallStub(getproperty_callable, context, deferred, key); | |
| 924 | |
| 925 Variable var_reason(this, MachineRepresentation::kTagged); | 967 Variable var_reason(this, MachineRepresentation::kTagged); |
| 926 | 968 |
| 927 Node* const is_debug_active = IsDebugActive(); | 969 Node* const is_debug_active = IsDebugActive(); |
| 928 Label run_handler(this), if_rejectpromise(this), promisehook_before(this), | 970 Label run_handler(this), if_rejectpromise(this), promisehook_before(this), |
| 929 promisehook_after(this), debug_pop(this); | 971 promisehook_after(this), debug_pop(this); |
| 930 | 972 |
| 931 GotoUnless(is_debug_active, &promisehook_before); | 973 GotoUnless(is_debug_active, &promisehook_before); |
| 932 CallRuntime(Runtime::kDebugPushPromise, context, deferred_promise); | 974 CallRuntime(Runtime::kDebugPushPromise, context, deferred_promise); |
| 933 Goto(&promisehook_before); | 975 Goto(&promisehook_before); |
| 934 | 976 |
| 935 Bind(&promisehook_before); | 977 Bind(&promisehook_before); |
| 936 { | 978 { |
| 937 GotoUnless(IsPromiseHookEnabled(), &run_handler); | 979 GotoUnless(IsPromiseHookEnabled(), &run_handler); |
| 938 CallRuntime(Runtime::kPromiseHookBefore, context, promise); | 980 CallRuntime(Runtime::kPromiseHookBefore, context, promise); |
| 939 Goto(&run_handler); | 981 Goto(&run_handler); |
| 940 } | 982 } |
| 941 | 983 |
| 942 Bind(&run_handler); | 984 Bind(&run_handler); |
| 943 { | 985 { |
| 944 Callable call_callable = CodeFactory::Call(isolate); | 986 Callable call_callable = CodeFactory::Call(isolate); |
| 945 | |
| 946 Node* const result = | 987 Node* const result = |
| 947 CallJS(call_callable, context, handler, UndefinedConstant(), value); | 988 CallJS(call_callable, context, handler, UndefinedConstant(), value); |
| 948 | 989 |
| 949 GotoIfException(result, &if_rejectpromise, &var_reason); | 990 GotoIfException(result, &if_rejectpromise, &var_reason); |
| 950 | 991 |
| 951 // TODO(gsathya): Remove this lookup by getting rid of the deferred object. | |
| 952 Node* const key = HeapConstant(isolate->factory()->resolve_string()); | |
| 953 Node* const on_resolve = | |
| 954 CallStub(getproperty_callable, context, deferred, key); | |
| 955 | |
| 956 Label if_internalhandler(this), if_customhandler(this, Label::kDeferred); | 992 Label if_internalhandler(this), if_customhandler(this, Label::kDeferred); |
| 957 Branch(IsUndefined(on_resolve), &if_internalhandler, &if_customhandler); | 993 Branch(IsUndefined(deferred_on_resolve), &if_internalhandler, |
| 994 &if_customhandler); |
| 958 | 995 |
| 959 Bind(&if_internalhandler); | 996 Bind(&if_internalhandler); |
| 960 InternalResolvePromise(context, deferred_promise, result); | 997 InternalResolvePromise(context, deferred_promise, result); |
| 961 Goto(&promisehook_after); | 998 Goto(&promisehook_after); |
| 962 | 999 |
| 963 Bind(&if_customhandler); | 1000 Bind(&if_customhandler); |
| 964 { | 1001 { |
| 965 Node* const maybe_exception = CallJS(call_callable, context, on_resolve, | 1002 Node* const maybe_exception = |
| 966 UndefinedConstant(), result); | 1003 CallJS(call_callable, context, deferred_on_resolve, |
| 1004 UndefinedConstant(), result); |
| 967 GotoIfException(maybe_exception, &if_rejectpromise, &var_reason); | 1005 GotoIfException(maybe_exception, &if_rejectpromise, &var_reason); |
| 968 Goto(&promisehook_after); | 1006 Goto(&promisehook_after); |
| 969 } | 1007 } |
| 970 } | 1008 } |
| 971 | 1009 |
| 972 Bind(&if_rejectpromise); | 1010 Bind(&if_rejectpromise); |
| 973 { | 1011 { |
| 974 // TODO(gsathya): Remove this lookup by getting rid of the deferred object. | |
| 975 Node* const key = HeapConstant(isolate->factory()->reject_string()); | |
| 976 Node* const on_reject = | |
| 977 CallStub(getproperty_callable, context, deferred, key); | |
| 978 | |
| 979 Callable promise_handle_reject = CodeFactory::PromiseHandleReject(isolate); | 1012 Callable promise_handle_reject = CodeFactory::PromiseHandleReject(isolate); |
| 980 CallStub(promise_handle_reject, context, deferred_promise, on_reject, | 1013 CallStub(promise_handle_reject, context, deferred_promise, |
| 981 var_reason.value()); | 1014 deferred_on_reject, var_reason.value()); |
| 982 Goto(&promisehook_after); | 1015 Goto(&promisehook_after); |
| 983 } | 1016 } |
| 984 | 1017 |
| 985 Bind(&promisehook_after); | 1018 Bind(&promisehook_after); |
| 986 { | 1019 { |
| 987 GotoUnless(IsPromiseHookEnabled(), &debug_pop); | 1020 GotoUnless(IsPromiseHookEnabled(), &debug_pop); |
| 988 CallRuntime(Runtime::kPromiseHookAfter, context, promise); | 1021 CallRuntime(Runtime::kPromiseHookAfter, context, promise); |
| 989 Goto(&debug_pop); | 1022 Goto(&debug_pop); |
| 990 } | 1023 } |
| 991 | 1024 |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1031 CallStub(getproperty_callable, context, promise, then_str); | 1064 CallStub(getproperty_callable, context, promise, then_str); |
| 1032 Callable call_callable = CodeFactory::Call(isolate); | 1065 Callable call_callable = CodeFactory::Call(isolate); |
| 1033 Node* const result = | 1066 Node* const result = |
| 1034 CallJS(call_callable, context, then, promise, on_resolve, on_reject); | 1067 CallJS(call_callable, context, then, promise, on_resolve, on_reject); |
| 1035 Return(result); | 1068 Return(result); |
| 1036 } | 1069 } |
| 1037 } | 1070 } |
| 1038 | 1071 |
| 1039 } // namespace internal | 1072 } // namespace internal |
| 1040 } // namespace v8 | 1073 } // namespace v8 |
| OLD | NEW |