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

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

Issue 2541283002: [promises] Port ResolvePromise to TF (Closed)
Patch Set: fix nits Created 4 years 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
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 4
5 #include "src/builtins/builtins-utils.h" 5 #include "src/builtins/builtins-utils.h"
6 #include "src/builtins/builtins.h" 6 #include "src/builtins/builtins.h"
7 #include "src/code-factory.h" 7 #include "src/code-factory.h"
8 #include "src/code-stub-assembler.h" 8 #include "src/code-stub-assembler.h"
9 #include "src/promise-utils.h" 9 #include "src/promise-utils.h"
10 10
11 namespace v8 { 11 namespace v8 {
12 namespace internal { 12 namespace internal {
13 13
14 // ES#sec-promise-resolve-functions
15 // Promise Resolve Functions
16 BUILTIN(PromiseResolveClosure) {
17 HandleScope scope(isolate);
18
19 Handle<Context> context(isolate->context(), isolate);
20
21 if (PromiseUtils::HasAlreadyVisited(context)) {
22 return isolate->heap()->undefined_value();
23 }
24
25 PromiseUtils::SetAlreadyVisited(context);
26 Handle<JSObject> promise = handle(PromiseUtils::GetPromise(context), isolate);
27 Handle<Object> value = args.atOrUndefined(isolate, 1);
28
29 MaybeHandle<Object> maybe_result;
30 Handle<Object> argv[] = {promise, value};
31 RETURN_FAILURE_ON_EXCEPTION(
32 isolate, Execution::Call(isolate, isolate->promise_resolve(),
33 isolate->factory()->undefined_value(),
34 arraysize(argv), argv));
35 return isolate->heap()->undefined_value();
36 }
37
38 // ES#sec-promise-reject-functions 14 // ES#sec-promise-reject-functions
39 // Promise Reject Functions 15 // Promise Reject Functions
40 BUILTIN(PromiseRejectClosure) { 16 BUILTIN(PromiseRejectClosure) {
41 HandleScope scope(isolate); 17 HandleScope scope(isolate);
42 18
43 Handle<Context> context(isolate->context(), isolate); 19 Handle<Context> context(isolate->context(), isolate);
44 20
45 if (PromiseUtils::HasAlreadyVisited(context)) { 21 if (PromiseUtils::HasAlreadyVisited(context)) {
46 return isolate->heap()->undefined_value(); 22 return isolate->heap()->undefined_value();
47 } 23 }
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
79 55
80 return *isolate->factory()->NewJSArrayWithElements(result, FAST_ELEMENTS, 2, 56 return *isolate->factory()->NewJSArrayWithElements(result, FAST_ELEMENTS, 2,
81 NOT_TENURED); 57 NOT_TENURED);
82 } 58 }
83 59
84 void PromiseInit(CodeStubAssembler* a, compiler::Node* promise, 60 void PromiseInit(CodeStubAssembler* a, compiler::Node* promise,
85 compiler::Node* status, compiler::Node* result) { 61 compiler::Node* status, compiler::Node* result) {
86 CSA_ASSERT(a, a->TaggedIsSmi(status)); 62 CSA_ASSERT(a, a->TaggedIsSmi(status));
87 a->StoreObjectField(promise, JSPromise::kStatusOffset, status); 63 a->StoreObjectField(promise, JSPromise::kStatusOffset, status);
88 a->StoreObjectField(promise, JSPromise::kResultOffset, result); 64 a->StoreObjectField(promise, JSPromise::kResultOffset, result);
65 a->StoreObjectField(promise, JSPromise::kFlagsOffset, a->SmiConstant(0));
89 } 66 }
90 67
91 void Builtins::Generate_PromiseConstructor( 68 void Builtins::Generate_PromiseConstructor(
92 compiler::CodeAssemblerState* state) { 69 compiler::CodeAssemblerState* state) {
93 CodeStubAssembler a(state); 70 CodeStubAssembler a(state);
94 typedef CodeStubAssembler::Variable Variable; 71 typedef CodeStubAssembler::Variable Variable;
95 typedef CodeStubAssembler::Label Label; 72 typedef CodeStubAssembler::Label Label;
96 typedef compiler::Node Node; 73 typedef compiler::Node Node;
97 74
98 Node* const executor = a.Parameter(1); 75 Node* const executor = a.Parameter(1);
(...skipping 180 matching lines...) Expand 10 before | Expand all | Expand 10 after
279 { 256 {
280 Node* const message_id = a->SmiConstant(msg_template); 257 Node* const message_id = a->SmiConstant(msg_template);
281 a->CallRuntime(Runtime::kThrowTypeError, context, message_id); 258 a->CallRuntime(Runtime::kThrowTypeError, context, message_id);
282 var_value_map.Bind(a->UndefinedConstant()); 259 var_value_map.Bind(a->UndefinedConstant());
283 a->Goto(&out); // Never reached. 260 a->Goto(&out); // Never reached.
284 } 261 }
285 262
286 a->Bind(&out); 263 a->Bind(&out);
287 return var_value_map.value(); 264 return var_value_map.value();
288 } 265 }
266
289 } // namespace 267 } // namespace
290 268
291 void Builtins::Generate_IsPromise(compiler::CodeAssemblerState* state) { 269 void Builtins::Generate_IsPromise(compiler::CodeAssemblerState* state) {
292 CodeStubAssembler a(state); 270 CodeStubAssembler a(state);
293 typedef compiler::Node Node; 271 typedef compiler::Node Node;
294 typedef CodeStubAssembler::Label Label; 272 typedef CodeStubAssembler::Label Label;
295 273
296 Node* const maybe_promise = a.Parameter(1); 274 Node* const maybe_promise = a.Parameter(1);
297 Label if_notpromise(&a, Label::kDeferred); 275 Label if_notpromise(&a, Label::kDeferred);
298 276
299 a.GotoIf(a.TaggedIsSmi(maybe_promise), &if_notpromise); 277 a.GotoIf(a.TaggedIsSmi(maybe_promise), &if_notpromise);
300 278
301 Node* const result = a.SelectBooleanConstant( 279 Node* const result = a.SelectBooleanConstant(
302 a.HasInstanceType(maybe_promise, JS_PROMISE_TYPE)); 280 a.HasInstanceType(maybe_promise, JS_PROMISE_TYPE));
303 a.Return(result); 281 a.Return(result);
304 282
305 a.Bind(&if_notpromise); 283 a.Bind(&if_notpromise);
306 a.Return(a.FalseConstant()); 284 a.Return(a.FalseConstant());
307 } 285 }
308 286
309 namespace { 287 namespace {
288
289 compiler::Node* PromiseHasHandler(CodeStubAssembler* a,
290 compiler::Node* promise) {
291 typedef compiler::Node Node;
292
293 Node* const flags = a->LoadObjectField(promise, JSPromise::kFlagsOffset);
294 return a->IsSetWord(a->SmiUntag(flags), 1 << JSPromise::kHasHandlerBit);
295 }
296
297 void PromiseSetHasHandler(CodeStubAssembler* a, compiler::Node* promise) {
298 typedef compiler::Node Node;
299
300 Node* const flags = a->LoadObjectField(promise, JSPromise::kFlagsOffset);
301 Node* const new_flags =
302 a->WordOr(flags, a->IntPtrConstant(1 << JSPromise::kHasHandlerBit));
303 a->StoreObjectField(promise, JSPromise::kFlagsOffset, a->SmiTag(new_flags));
304 }
305
310 compiler::Node* SpeciesConstructor(CodeStubAssembler* a, Isolate* isolate, 306 compiler::Node* SpeciesConstructor(CodeStubAssembler* a, Isolate* isolate,
311 compiler::Node* context, 307 compiler::Node* context,
312 compiler::Node* object, 308 compiler::Node* object,
313 compiler::Node* default_constructor) { 309 compiler::Node* default_constructor) {
314 typedef compiler::Node Node; 310 typedef compiler::Node Node;
315 typedef CodeStubAssembler::Label Label; 311 typedef CodeStubAssembler::Label Label;
316 typedef CodeStubAssembler::Variable Variable; 312 typedef CodeStubAssembler::Variable Variable;
317 313
318 Variable var_result(a, MachineRepresentation::kTagged); 314 Variable var_result(a, MachineRepresentation::kTagged);
319 var_result.Bind(default_constructor); 315 var_result.Bind(default_constructor);
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
397 393
398 compiler::Node* InternalPerformPromiseThen(CodeStubAssembler* a, 394 compiler::Node* InternalPerformPromiseThen(CodeStubAssembler* a,
399 compiler::Node* context, 395 compiler::Node* context,
400 compiler::Node* promise, 396 compiler::Node* promise,
401 compiler::Node* on_resolve, 397 compiler::Node* on_resolve,
402 compiler::Node* on_reject, 398 compiler::Node* on_reject,
403 compiler::Node* deferred) { 399 compiler::Node* deferred) {
404 typedef CodeStubAssembler::Variable Variable; 400 typedef CodeStubAssembler::Variable Variable;
405 typedef CodeStubAssembler::Label Label; 401 typedef CodeStubAssembler::Label Label;
406 typedef compiler::Node Node; 402 typedef compiler::Node Node;
407
408 Isolate* isolate = a->isolate(); 403 Isolate* isolate = a->isolate();
409 Node* const native_context = a->LoadNativeContext(context); 404 Node* const native_context = a->LoadNativeContext(context);
410 405
411 Variable var_on_resolve(a, MachineRepresentation::kTagged), 406 Variable var_on_resolve(a, MachineRepresentation::kTagged),
412 var_on_reject(a, MachineRepresentation::kTagged); 407 var_on_reject(a, MachineRepresentation::kTagged);
413 408
414 var_on_resolve.Bind(on_resolve); 409 var_on_resolve.Bind(on_resolve);
415 var_on_reject.Bind(on_reject); 410 var_on_reject.Bind(on_reject);
416 411
417 Label out(a), if_onresolvenotcallable(a), onrejectcheck(a), 412 Label out(a), if_onresolvenotcallable(a), onrejectcheck(a),
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after
529 &reject); 524 &reject);
530 525
531 // TODO(gsathya): Move this to TF. 526 // TODO(gsathya): Move this to TF.
532 a->CallRuntime(Runtime::kEnqueuePromiseReactionJob, context, result, 527 a->CallRuntime(Runtime::kEnqueuePromiseReactionJob, context, result,
533 var_on_resolve.value(), deferred, 528 var_on_resolve.value(), deferred,
534 a->SmiConstant(kPromiseFulfilled)); 529 a->SmiConstant(kPromiseFulfilled));
535 a->Goto(&out); 530 a->Goto(&out);
536 531
537 a->Bind(&reject); 532 a->Bind(&reject);
538 { 533 {
539 Callable getproperty_callable = CodeFactory::GetProperty(isolate); 534 Node* const has_handler = PromiseHasHandler(a, promise);
540 Node* const key =
541 a->HeapConstant(isolate->factory()->promise_has_handler_symbol());
542 Node* const has_handler =
543 a->CallStub(getproperty_callable, context, promise, key);
544
545 Label enqueue(a); 535 Label enqueue(a);
546 536
547 // TODO(gsathya): Fold these runtime calls and move to TF. 537 // TODO(gsathya): Fold these runtime calls and move to TF.
548 a->GotoIf(a->WordEqual(has_handler, a->TrueConstant()), &enqueue); 538 a->GotoIf(has_handler, &enqueue);
549 a->CallRuntime(Runtime::kPromiseRevokeReject, context, promise); 539 a->CallRuntime(Runtime::kPromiseRevokeReject, context, promise);
550 a->Goto(&enqueue); 540 a->Goto(&enqueue);
551 541
552 a->Bind(&enqueue); 542 a->Bind(&enqueue);
553 { 543 {
554 a->CallRuntime(Runtime::kEnqueuePromiseReactionJob, context, result, 544 a->CallRuntime(Runtime::kEnqueuePromiseReactionJob, context, result,
555 var_on_reject.value(), deferred, 545 var_on_reject.value(), deferred,
556 a->SmiConstant(kPromiseRejected)); 546 a->SmiConstant(kPromiseRejected));
557 547
558 a->Goto(&out); 548 a->Goto(&out);
559 } 549 }
560 } 550 }
561 } 551 }
562 } 552 }
563 553
564 a->Bind(&out); 554 a->Bind(&out);
565 // TODO(gsathya): Protect with debug check. 555 PromiseSetHasHandler(a, promise);
566 a->CallRuntime(
567 Runtime::kSetProperty, context, promise,
568 a->HeapConstant(isolate->factory()->promise_has_handler_symbol()),
569 a->TrueConstant(), a->SmiConstant(STRICT));
570 556
571 // TODO(gsathya): This call will be removed once we don't have to 557 // TODO(gsathya): This call will be removed once we don't have to
572 // deal with deferred objects. 558 // deal with deferred objects.
573 Callable getproperty_callable = CodeFactory::GetProperty(isolate); 559 Callable getproperty_callable = CodeFactory::GetProperty(isolate);
574 Node* const key = 560 Node* const key =
575 a->HeapConstant(isolate->factory()->NewStringFromAsciiChecked("promise")); 561 a->HeapConstant(isolate->factory()->NewStringFromAsciiChecked("promise"));
576 Node* const result = 562 Node* const result =
577 a->CallStub(getproperty_callable, context, deferred, key); 563 a->CallStub(getproperty_callable, context, deferred, key);
578 564
579 return result; 565 return result;
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
660 } 646 }
661 647
662 // 5. Return PerformPromiseThen(promise, onFulfilled, onRejected, 648 // 5. Return PerformPromiseThen(promise, onFulfilled, onRejected,
663 // resultCapability). 649 // resultCapability).
664 a.Bind(&perform_promise_then); 650 a.Bind(&perform_promise_then);
665 Node* const result = InternalPerformPromiseThen( 651 Node* const result = InternalPerformPromiseThen(
666 &a, context, promise, on_resolve, on_reject, var_deferred.value()); 652 &a, context, promise, on_resolve, on_reject, var_deferred.value());
667 a.Return(result); 653 a.Return(result);
668 } 654 }
669 655
656 namespace {
657
658 // Promise fast path implementations rely on unmodified JSPromise instances.
659 // We use a fairly coarse granularity for this and simply check whether both
660 // the promise itself is unmodified (i.e. its map has not changed) and its
661 // prototype is unmodified.
662 // TODO(gsathya): Refactor this out to prevent code dupe with builtins-regexp
663 void BranchIfFastPath(CodeStubAssembler* a, compiler::Node* context,
664 compiler::Node* promise,
665 CodeStubAssembler::Label* if_isunmodified,
666 CodeStubAssembler::Label* if_ismodified) {
667 typedef compiler::Node Node;
668
669 // TODO(gsathya): Assert if promise is receiver
670 Node* const map = a->LoadMap(promise);
671 Node* const native_context = a->LoadNativeContext(context);
672 Node* const promise_fun =
673 a->LoadContextElement(native_context, Context::PROMISE_FUNCTION_INDEX);
674 Node* const initial_map =
675 a->LoadObjectField(promise_fun, JSFunction::kPrototypeOrInitialMapOffset);
676 Node* const has_initialmap = a->WordEqual(map, initial_map);
677
678 a->GotoUnless(has_initialmap, if_ismodified);
679
680 Node* const initial_proto_initial_map = a->LoadContextElement(
681 native_context, Context::PROMISE_PROTOTYPE_MAP_INDEX);
682 Node* const proto_map = a->LoadMap(a->LoadMapPrototype(map));
683 Node* const proto_has_initialmap =
684 a->WordEqual(proto_map, initial_proto_initial_map);
685
686 a->Branch(proto_has_initialmap, if_isunmodified, if_ismodified);
687 }
688
689 void InternalResolvePromise(CodeStubAssembler* a, compiler::Node* context,
690 compiler::Node* promise, compiler::Node* result,
691 CodeStubAssembler::Label* out) {
692 typedef CodeStubAssembler::Variable Variable;
693 typedef CodeStubAssembler::Label Label;
694 typedef compiler::Node Node;
695
696 Isolate* isolate = a->isolate();
697
698 Variable var_reason(a, MachineRepresentation::kTagged),
699 var_then(a, MachineRepresentation::kTagged);
700
701 Label do_enqueue(a), fulfill(a), if_cycle(a, Label::kDeferred),
702 if_rejectpromise(a, Label::kDeferred);
703
704 // 6. If SameValue(resolution, promise) is true, then
705 a->GotoIf(a->SameValue(promise, result, context), &if_cycle);
706
707 // 7. If Type(resolution) is not Object, then
708 a->GotoIf(a->TaggedIsSmi(result), &fulfill);
709 a->GotoUnless(a->IsJSReceiver(result), &fulfill);
710
711 Label if_nativepromise(a), if_notnativepromise(a, Label::kDeferred);
712 BranchIfFastPath(a, context, result, &if_nativepromise, &if_notnativepromise);
713
714 // Resolution is a native promise and if it's already resolved or
715 // rejected, shortcircuit the resolution procedure by directly
716 // reusing the value from the promise.
717 a->Bind(&if_nativepromise);
718 {
719 Node* const thenable_status =
720 a->LoadObjectField(result, JSPromise::kStatusOffset);
721 Node* const thenable_value =
722 a->LoadObjectField(result, JSPromise::kResultOffset);
723
724 Label if_isnotpending(a);
725 a->GotoUnless(a->SmiEqual(a->SmiConstant(kPromisePending), thenable_status),
726 &if_isnotpending);
727
728 // TODO(gsathya): Use a marker here instead of the actual then
729 // callback, and check for the marker in PromiseResolveThenableJob
730 // and perform PromiseThen.
731 Node* const native_context = a->LoadNativeContext(context);
732 Node* const then =
733 a->LoadContextElement(native_context, Context::PROMISE_THEN_INDEX);
734 var_then.Bind(then);
735 a->Goto(&do_enqueue);
736
737 a->Bind(&if_isnotpending);
738 {
739 Label if_fulfilled(a), if_rejected(a);
740 a->Branch(a->SmiEqual(a->SmiConstant(kPromiseFulfilled), thenable_status),
741 &if_fulfilled, &if_rejected);
742
743 a->Bind(&if_fulfilled);
744 {
745 a->CallRuntime(Runtime::kPromiseFulfill, context, promise,
746 a->SmiConstant(kPromiseFulfilled), thenable_value);
747 PromiseSetHasHandler(a, promise);
748 a->Goto(out);
749 }
750
751 a->Bind(&if_rejected);
752 {
753 Label reject(a);
754 Node* const has_handler = PromiseHasHandler(a, result);
755
756 // Promise has already been rejected, but had no handler.
757 // Revoke previously triggered reject event.
758 a->GotoIf(has_handler, &reject);
759 a->CallRuntime(Runtime::kPromiseRevokeReject, context, result);
760 a->Goto(&reject);
761
762 a->Bind(&reject);
763 // Don't cause a debug event as this case is forwarding a rejection
764 a->CallRuntime(Runtime::kPromiseReject, context, promise,
765 thenable_value, a->FalseConstant());
766 PromiseSetHasHandler(a, result);
767 a->Goto(out);
768 }
769 }
770 }
771
772 a->Bind(&if_notnativepromise);
773 {
774 // 8. Let then be Get(resolution, "then").
775 Node* const then_str = a->HeapConstant(isolate->factory()->then_string());
776 Callable getproperty_callable = CodeFactory::GetProperty(a->isolate());
777 Node* const then =
778 a->CallStub(getproperty_callable, context, result, then_str);
779
780 // 9. If then is an abrupt completion, then
781 a->GotoIfException(then, &if_rejectpromise, &var_reason);
782
783 // 11. If IsCallable(thenAction) is false, then
784 a->GotoIf(a->TaggedIsSmi(then), &fulfill);
785 Node* const then_map = a->LoadMap(then);
786 a->GotoUnless(a->IsCallableMap(then_map), &fulfill);
787 var_then.Bind(then);
788 a->Goto(&do_enqueue);
789 }
790
791 a->Bind(&do_enqueue);
792 {
793 Label enqueue(a);
794 a->GotoUnless(a->IsDebugActive(), &enqueue);
795 a->GotoIf(a->TaggedIsSmi(result), &enqueue);
796 a->GotoUnless(a->HasInstanceType(result, JS_PROMISE_TYPE), &enqueue);
797 // Mark the dependency of the new promise on the resolution
798 Node* const key =
799 a->HeapConstant(isolate->factory()->promise_handled_by_symbol());
800 a->CallRuntime(Runtime::kSetProperty, context, result, key, promise,
801 a->SmiConstant(STRICT));
802 a->Goto(&enqueue);
803
804 // 12. Perform EnqueueJob("PromiseJobs",
805 // PromiseResolveThenableJob, « promise, resolution, thenAction
806 // »).
807 a->Bind(&enqueue);
808 a->CallRuntime(Runtime::kEnqueuePromiseResolveThenableJob, context, promise,
809 result, var_then.value());
810 a->Goto(out);
811 }
812 // 7.b Return FulfillPromise(promise, resolution).
813 a->Bind(&fulfill);
814 {
815 a->CallRuntime(Runtime::kPromiseFulfill, context, promise,
816 a->SmiConstant(kPromiseFulfilled), result);
817 a->Goto(out);
818 }
819
820 a->Bind(&if_cycle);
821 {
822 // 6.a Let selfResolutionError be a newly created TypeError object.
823 Node* const message_id = a->SmiConstant(MessageTemplate::kPromiseCyclic);
824 Node* const error =
825 a->CallRuntime(Runtime::kNewTypeError, context, message_id, result);
826 var_reason.Bind(error);
827
828 // 6.b Return RejectPromise(promise, selfResolutionError).
829 a->Goto(&if_rejectpromise);
830 }
831
832 // 9.a Return RejectPromise(promise, then.[[Value]]).
833 a->Bind(&if_rejectpromise);
834 {
835 a->CallRuntime(Runtime::kPromiseReject, context, promise,
836 var_reason.value(), a->TrueConstant());
837 a->Goto(out);
838 }
839 }
840
841 } // namespace
842
843 // ES#sec-promise-resolve-functions
844 // Promise Resolve Functions
845 void Builtins::Generate_PromiseResolveClosure(
846 compiler::CodeAssemblerState* state) {
847 CodeStubAssembler a(state);
848 typedef compiler::Node Node;
849 typedef CodeStubAssembler::Label Label;
850
851 Node* const value = a.Parameter(1);
852 Node* const context = a.Parameter(4);
853
854 Label out(&a);
855
856 // 3. Let alreadyResolved be F.[[AlreadyResolved]].
857 Node* const has_already_visited_slot =
858 a.IntPtrConstant(PromiseUtils::kAlreadyVisitedSlot);
859
860 Node* const has_already_visited =
861 a.LoadFixedArrayElement(context, has_already_visited_slot);
862
863 // 4. If alreadyResolved.[[Value]] is true, return undefined.
864 a.GotoIf(a.SmiEqual(has_already_visited, a.SmiConstant(1)), &out);
865
866 // 5.Set alreadyResolved.[[Value]] to true.
867 a.StoreFixedArrayElement(context, has_already_visited_slot, a.SmiConstant(1));
868
869 // 2. Let promise be F.[[Promise]].
870 Node* const promise = a.LoadFixedArrayElement(
871 context, a.IntPtrConstant(PromiseUtils::kPromiseSlot));
872
873 InternalResolvePromise(&a, context, promise, value, &out);
874
875 a.Bind(&out);
876 a.Return(a.UndefinedConstant());
877 }
878
879 void Builtins::Generate_ResolvePromise(compiler::CodeAssemblerState* state) {
880 CodeStubAssembler a(state);
881 typedef compiler::Node Node;
882 typedef CodeStubAssembler::Label Label;
883
884 Node* const promise = a.Parameter(1);
885 Node* const result = a.Parameter(2);
886 Node* const context = a.Parameter(5);
887
888 Label out(&a);
889 InternalResolvePromise(&a, context, promise, result, &out);
890
891 a.Bind(&out);
892 a.Return(a.UndefinedConstant());
893 }
894
670 } // namespace internal 895 } // namespace internal
671 } // namespace v8 896 } // namespace v8
OLDNEW
« no previous file with comments | « src/builtins/builtins.h ('k') | src/contexts.h » ('j') | src/js/promise.js » ('J')

Powered by Google App Engine
This is Rietveld 408576698